nsswitch/wb_common.c

ソースコードを見る。

関数

BOOL winbind_env_set (void)
BOOL winbind_off (void)
BOOL winbind_on (void)
void free_response (struct winbindd_response *response)
void init_request (struct winbindd_request *request, int request_type)
static void init_response (struct winbindd_response *response)
void close_sock (void)
static int make_nonstd_fd_internals (int fd, int limit)
static int make_safe_fd (int fd)
static int winbind_named_pipe_sock (const char *dir)
static int winbind_open_pipe_sock (int recursing, int need_priv)
int write_sock (void *buffer, int count, int recursing, int need_priv)
static int read_sock (void *buffer, int count)
int read_reply (struct winbindd_response *response)
NSS_STATUS winbindd_send_request (int req_type, int need_priv, struct winbindd_request *request)
NSS_STATUS winbindd_get_response (struct winbindd_response *response)
NSS_STATUS winbindd_request_response (int req_type, struct winbindd_request *request, struct winbindd_response *response)
NSS_STATUS winbindd_priv_request_response (int req_type, struct winbindd_request *request, struct winbindd_response *response)

変数

int winbindd_fd = -1
static int is_privileged = 0


関数

BOOL winbind_env_set ( void   ) 

wb_common.c540 行で定義されています。

参照元 get_memberuids()sys_getgrouplist()winbindd_send_request().

00541 {
00542         char *env;
00543         
00544         if ((env=getenv(WINBINDD_DONT_ENV)) != NULL) {
00545                 if(strcmp(env, "1") == 0) {
00546                         return True;
00547                 }
00548         }
00549         return False;
00550 }

BOOL winbind_off ( void   ) 

wb_common.c678 行で定義されています。

参照元 get_memberuids()idmap_nss_sids_to_unixids()idmap_nss_unixids_to_sids()main()make_server_info_sam()sys_getgrouplist().

00679 {
00680         static char *s = CONST_DISCARD(char *, WINBINDD_DONT_ENV "=1");
00681 
00682         return putenv(s) != -1;
00683 }

BOOL winbind_on ( void   ) 

wb_common.c685 行で定義されています。

参照元 get_memberuids()idmap_nss_sids_to_unixids()idmap_nss_unixids_to_sids()sys_getgrouplist().

00686 {
00687         static char *s = CONST_DISCARD(char *, WINBINDD_DONT_ENV "=0");
00688 
00689         return putenv(s) != -1;
00690 }

void free_response ( struct winbindd_response response  ) 

wb_common.c40 行で定義されています。

参照先 winbindd_response::datawinbindd_response::extra_data.

参照元 _nss_winbind_endgrent()_nss_winbind_endpwent()_nss_winbind_getgrgid_r()_nss_winbind_getgrnam_r()_nss_winbind_getpwent_r()_nss_winbind_getpwnam_r()_nss_winbind_getpwuid_r()_nss_winbind_getusersids()_nss_winbind_gidtosid()_nss_winbind_hosts_getbyaddr()_nss_winbind_hosts_getbyname()_nss_winbind_ipnodes_getbyname()_nss_winbind_nametosid()_nss_winbind_setgrent()_nss_winbind_setpwent()_nss_winbind_sidtoname()_nss_winbind_uidtosid()contact_winbind_auth_crap()contact_winbind_change_pswd_auth_crap()do_ccache_ntlm_auth()read_reply()wb_aix_authenticate()wb_aix_chpass()wb_aix_getgrgid()wb_aix_getgrnam()wb_aix_getgrset()wb_aix_getpwnam()wb_aix_getpwuid()wb_aix_lsgroup()wb_aix_lsuser()winbind_callback()winbind_getgrent()winbindd_get_response().

00041 {
00042         /* Free any allocated extra_data */
00043 
00044         if (response)
00045                 SAFE_FREE(response->extra_data.data);
00046 }

void init_request ( struct winbindd_request request,
int  request_type 
)

wb_common.c50 行で定義されています。

参照先 winbindd_request::cmdwinbindd_request::lengthwinbindd_request::pid.

参照元 pam_winbind_request()winbindd_send_request().

00051 {
00052         request->length = sizeof(struct winbindd_request);
00053 
00054         request->cmd = (enum winbindd_cmd)request_type;
00055         request->pid = getpid();
00056 
00057 }

static void init_response ( struct winbindd_response response  )  [static]

wb_common.c61 行で定義されています。

参照先 winbindd_response::resultWINBINDD_ERROR.

参照元 winbindd_get_response().

00062 {
00063         /* Initialise return value */
00064 
00065         response->result = WINBINDD_ERROR;
00066 }

void close_sock ( void   ) 

wb_common.c70 行で定義されています。

参照先 winbindd_fd.

参照元 pam_winbind_request()read_sock()winbind_open_pipe_sock()write_sock().

00071 {
00072         if (winbindd_fd != -1) {
00073                 close(winbindd_fd);
00074                 winbindd_fd = -1;
00075         }
00076 }

static int make_nonstd_fd_internals ( int  fd,
int  limit 
) [static]

wb_common.c83 行で定義されています。

参照元 make_safe_fd().

00084 {
00085         int new_fd;
00086         if (fd >= 0 && fd <= 2) {
00087 #ifdef F_DUPFD 
00088                 if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) {
00089                         return -1;
00090                 }
00091                 /* Paranoia */
00092                 if (new_fd < 3) {
00093                         close(new_fd);
00094                         return -1;
00095                 }
00096                 close(fd);
00097                 return new_fd;
00098 #else
00099                 if (limit <= 0)
00100                         return -1;
00101                 
00102                 new_fd = dup(fd);
00103                 if (new_fd == -1) 
00104                         return -1;
00105 
00106                 /* use the program stack to hold our list of FDs to close */
00107                 new_fd = make_nonstd_fd_internals(new_fd, limit - 1);
00108                 close(fd);
00109                 return new_fd;
00110 #endif
00111         }
00112         return fd;
00113 }

static int make_safe_fd ( int  fd  )  [static]

wb_common.c123 行で定義されています。

参照先 flagsmake_nonstd_fd_internals()result.

参照元 winbind_named_pipe_sock().

00124 {
00125         int result, flags;
00126         int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT);
00127         if (new_fd == -1) {
00128                 close(fd);
00129                 return -1;
00130         }
00131 
00132         /* Socket should be nonblocking. */
00133 #ifdef O_NONBLOCK
00134 #define FLAG_TO_SET O_NONBLOCK
00135 #else
00136 #ifdef SYSV
00137 #define FLAG_TO_SET O_NDELAY
00138 #else /* BSD */
00139 #define FLAG_TO_SET FNDELAY
00140 #endif
00141 #endif
00142 
00143         if ((flags = fcntl(new_fd, F_GETFL)) == -1) {
00144                 close(new_fd);
00145                 return -1;
00146         }
00147 
00148         flags |= FLAG_TO_SET;
00149         if (fcntl(new_fd, F_SETFL, flags) == -1) {
00150                 close(new_fd);
00151                 return -1;
00152         }
00153 
00154 #undef FLAG_TO_SET
00155 
00156         /* Socket should be closed on exec() */
00157 #ifdef FD_CLOEXEC
00158         result = flags = fcntl(new_fd, F_GETFD, 0);
00159         if (flags >= 0) {
00160                 flags |= FD_CLOEXEC;
00161                 result = fcntl( new_fd, F_SETFD, flags );
00162         }
00163         if (result < 0) {
00164                 close(new_fd);
00165                 return -1;
00166         }
00167 #endif
00168         return new_fd;
00169 }

static int winbind_named_pipe_sock ( const char *  dir  )  [static]

wb_common.c173 行で定義されています。

参照先 errnofdmake_safe_fd().

参照元 winbind_open_pipe_sock().

00174 {
00175         struct sockaddr_un sunaddr;
00176         struct stat st;
00177         pstring path;
00178         int fd;
00179         int wait_time;
00180         int slept;
00181         
00182         /* Check permissions on unix socket directory */
00183         
00184         if (lstat(dir, &st) == -1) {
00185                 errno = ENOENT;
00186                 return -1;
00187         }
00188         
00189         if (!S_ISDIR(st.st_mode) || 
00190             (st.st_uid != 0 && st.st_uid != geteuid())) {
00191                 errno = ENOENT;
00192                 return -1;
00193         }
00194         
00195         /* Connect to socket */
00196         
00197         strncpy(path, dir, sizeof(path) - 1);
00198         path[sizeof(path) - 1] = '\0';
00199         
00200         strncat(path, "/", sizeof(path) - 1 - strlen(path));
00201         path[sizeof(path) - 1] = '\0';
00202         
00203         strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1 - strlen(path));
00204         path[sizeof(path) - 1] = '\0';
00205         
00206         ZERO_STRUCT(sunaddr);
00207         sunaddr.sun_family = AF_UNIX;
00208         strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1);
00209         
00210         /* If socket file doesn't exist, don't bother trying to connect
00211            with retry.  This is an attempt to make the system usable when
00212            the winbindd daemon is not running. */
00213 
00214         if (lstat(path, &st) == -1) {
00215                 errno = ENOENT;
00216                 return -1;
00217         }
00218         
00219         /* Check permissions on unix socket file */
00220         
00221         if (!S_ISSOCK(st.st_mode) || 
00222             (st.st_uid != 0 && st.st_uid != geteuid())) {
00223                 errno = ENOENT;
00224                 return -1;
00225         }
00226         
00227         /* Connect to socket */
00228         
00229         if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
00230                 return -1;
00231         }
00232 
00233         /* Set socket non-blocking and close on exec. */
00234 
00235         if ((fd = make_safe_fd( fd)) == -1) {
00236                 return fd;
00237         }
00238 
00239         for (wait_time = 0; connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1;
00240                         wait_time += slept) {
00241                 struct timeval tv;
00242                 fd_set w_fds;
00243                 int ret;
00244                 int connect_errno = 0;
00245                 socklen_t errnosize;
00246 
00247                 if (wait_time >= CONNECT_TIMEOUT)
00248                         goto error_out;
00249 
00250                 switch (errno) {
00251                         case EINPROGRESS:
00252                                 FD_ZERO(&w_fds);
00253                                 FD_SET(fd, &w_fds);
00254                                 tv.tv_sec = CONNECT_TIMEOUT - wait_time;
00255                                 tv.tv_usec = 0;
00256 
00257                                 ret = select(fd + 1, NULL, &w_fds, NULL, &tv);
00258 
00259                                 if (ret > 0) {
00260                                         errnosize = sizeof(connect_errno);
00261 
00262                                         ret = getsockopt(fd, SOL_SOCKET,
00263                                                         SO_ERROR, &connect_errno, &errnosize);
00264 
00265                                         if (ret >= 0 && connect_errno == 0) {
00266                                                 /* Connect succeed */
00267                                                 goto out;
00268                                         }
00269                                 }
00270 
00271                                 slept = CONNECT_TIMEOUT;
00272                                 break;
00273                         case EAGAIN:
00274                                 slept = rand() % 3 + 1;
00275                                 sleep(slept);
00276                                 break;
00277                         default:
00278                                 goto error_out;
00279                 }
00280 
00281         }
00282 
00283   out:
00284 
00285         return fd;
00286 
00287   error_out:
00288 
00289         close(fd);
00290         return -1;
00291 }

static int winbind_open_pipe_sock ( int  recursing,
int  need_priv 
) [static]

wb_common.c295 行で定義されています。

参照先 close_sock()winbindd_response::datawinbindd_response::extra_datafdwinbindd_request::flagswinbindd_response::interface_versionis_privilegedNSS_STATUS_SUCCESSwinbind_named_pipe_sock()winbindd_fdWINBINDD_INTERFACE_VERSIONWINBINDD_PRIV_PIPE_DIRwinbindd_request_response().

参照元 write_sock().

00296 {
00297 #ifdef HAVE_UNIXSOCKET
00298         static pid_t our_pid;
00299         struct winbindd_request request;
00300         struct winbindd_response response;
00301         ZERO_STRUCT(request);
00302         ZERO_STRUCT(response);
00303 
00304         if (our_pid != getpid()) {
00305                 close_sock();
00306                 our_pid = getpid();
00307         }
00308 
00309         if ((need_priv != 0) && (is_privileged == 0)) {
00310                 close_sock();
00311         }
00312         
00313         if (winbindd_fd != -1) {
00314                 return winbindd_fd;
00315         }
00316 
00317         if (recursing) {
00318                 return -1;
00319         }
00320 
00321         if ((winbindd_fd = winbind_named_pipe_sock(WINBINDD_SOCKET_DIR)) == -1) {
00322                 return -1;
00323         }
00324 
00325         is_privileged = 0;
00326 
00327         /* version-check the socket */
00328 
00329         request.flags = WBFLAG_RECURSE;
00330         if ((winbindd_request_response(WINBINDD_INTERFACE_VERSION, &request, &response) != NSS_STATUS_SUCCESS) || (response.data.interface_version != WINBIND_INTERFACE_VERSION)) {
00331                 close_sock();
00332                 return -1;
00333         }
00334 
00335         /* try and get priv pipe */
00336 
00337         request.flags = WBFLAG_RECURSE;
00338         if (winbindd_request_response(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) {
00339                 int fd;
00340                 if ((fd = winbind_named_pipe_sock((char *)response.extra_data.data)) != -1) {
00341                         close(winbindd_fd);
00342                         winbindd_fd = fd;
00343                         is_privileged = 1;
00344                 }
00345         }
00346 
00347         if ((need_priv != 0) && (is_privileged == 0)) {
00348                 return -1;
00349         }
00350 
00351         SAFE_FREE(response.extra_data.data);
00352 
00353         return winbindd_fd;
00354 #else
00355         return -1;
00356 #endif /* HAVE_UNIXSOCKET */
00357 }

int write_sock ( void *  buffer,
int  count,
int  recursing,
int  need_priv 
)

wb_common.c361 行で定義されています。

参照先 close_sock()errnoresultwinbind_open_pipe_sock()winbindd_fd.

参照元 pam_winbind_request()winbindd_send_request().

00362 {
00363         int result, nwritten;
00364         
00365         /* Open connection to winbind daemon */
00366         
00367  restart:
00368         
00369         if (winbind_open_pipe_sock(recursing, need_priv) == -1) {
00370                 errno = ENOENT;
00371                 return -1;
00372         }
00373         
00374         /* Write data to socket */
00375         
00376         nwritten = 0;
00377         
00378         while(nwritten < count) {
00379                 struct timeval tv;
00380                 fd_set r_fds;
00381                 
00382                 /* Catch pipe close on other end by checking if a read()
00383                    call would not block by calling select(). */
00384 
00385                 FD_ZERO(&r_fds);
00386                 FD_SET(winbindd_fd, &r_fds);
00387                 ZERO_STRUCT(tv);
00388                 
00389                 if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) {
00390                         close_sock();
00391                         return -1;                   /* Select error */
00392                 }
00393                 
00394                 /* Write should be OK if fd not available for reading */
00395                 
00396                 if (!FD_ISSET(winbindd_fd, &r_fds)) {
00397                         
00398                         /* Do the write */
00399                         
00400                         result = write(winbindd_fd,
00401                                        (char *)buffer + nwritten, 
00402                                        count - nwritten);
00403                         
00404                         if ((result == -1) || (result == 0)) {
00405                                 
00406                                 /* Write failed */
00407                                 
00408                                 close_sock();
00409                                 return -1;
00410                         }
00411                         
00412                         nwritten += result;
00413                         
00414                 } else {
00415                         
00416                         /* Pipe has closed on remote end */
00417                         
00418                         close_sock();
00419                         goto restart;
00420                 }
00421         }
00422         
00423         return nwritten;
00424 }

static int read_sock ( void *  buffer,
int  count 
) [static]

wb_common.c428 行で定義されています。

参照先 close_sock()resultwinbindd_fd.

参照元 read_reply().

00429 {
00430         int nread = 0;
00431         int total_time = 0, selret;
00432 
00433         if (winbindd_fd == -1) {
00434                 return -1;
00435         }
00436 
00437         /* Read data from socket */
00438         while(nread < count) {
00439                 struct timeval tv;
00440                 fd_set r_fds;
00441                 
00442                 /* Catch pipe close on other end by checking if a read()
00443                    call would not block by calling select(). */
00444 
00445                 FD_ZERO(&r_fds);
00446                 FD_SET(winbindd_fd, &r_fds);
00447                 ZERO_STRUCT(tv);
00448                 /* Wait for 5 seconds for a reply. May need to parameterise this... */
00449                 tv.tv_sec = 5;
00450 
00451                 if ((selret = select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv)) == -1) {
00452                         close_sock();
00453                         return -1;                   /* Select error */
00454                 }
00455                 
00456                 if (selret == 0) {
00457                         /* Not ready for read yet... */
00458                         if (total_time >= 30) {
00459                                 /* Timeout */
00460                                 close_sock();
00461                                 return -1;
00462                         }
00463                         total_time += 5;
00464                         continue;
00465                 }
00466 
00467                 if (FD_ISSET(winbindd_fd, &r_fds)) {
00468                         
00469                         /* Do the Read */
00470                         
00471                         int result = read(winbindd_fd, (char *)buffer + nread, 
00472                               count - nread);
00473                         
00474                         if ((result == -1) || (result == 0)) {
00475                                 
00476                                 /* Read failed.  I think the only useful thing we
00477                                    can do here is just return -1 and fail since the
00478                                    transaction has failed half way through. */
00479                         
00480                                 close_sock();
00481                                 return -1;
00482                         }
00483                         
00484                         nread += result;
00485                         
00486                 }
00487         }
00488         
00489         return nread;
00490 }

int read_reply ( struct winbindd_response response  ) 

wb_common.c494 行で定義されています。

参照先 winbindd_response::datawinbindd_response::extra_datafree_response()winbindd_response::lengthread_sock().

参照元 pam_winbind_request()winbindd_get_response().

00495 {
00496         int result1, result2 = 0;
00497 
00498         if (!response) {
00499                 return -1;
00500         }
00501         
00502         /* Read fixed length response */
00503         
00504         if ((result1 = read_sock(response, sizeof(struct winbindd_response)))
00505             == -1) {
00506                 
00507                 return -1;
00508         }
00509         
00510         /* We actually send the pointer value of the extra_data field from
00511            the server.  This has no meaning in the client's address space
00512            so we clear it out. */
00513 
00514         response->extra_data.data = NULL;
00515 
00516         /* Read variable length response */
00517         
00518         if (response->length > sizeof(struct winbindd_response)) {
00519                 int extra_data_len = response->length - 
00520                         sizeof(struct winbindd_response);
00521                 
00522                 /* Mallocate memory for extra data */
00523                 
00524                 if (!(response->extra_data.data = malloc(extra_data_len))) {
00525                         return -1;
00526                 }
00527                 
00528                 if ((result2 = read_sock(response->extra_data.data, extra_data_len))
00529                     == -1) {
00530                         free_response(response);
00531                         return -1;
00532                 }
00533         }
00534         
00535         /* Return total amount of data read */
00536         
00537         return result1 + result2;
00538 }

NSS_STATUS winbindd_send_request ( int  req_type,
int  need_priv,
struct winbindd_request request 
)

wb_common.c556 行で定義されています。

参照先 errnowinbindd_request::flagsinit_request()NSS_STATUS_NOTFOUNDNSS_STATUS_SUCCESSNSS_STATUS_UNAVAILwinbind_env_set()write_sock().

参照元 send_next_request()winbindd_priv_request_response()winbindd_request_response().

00558 {
00559         struct winbindd_request lrequest;
00560 
00561         /* Check for our tricky environment variable */
00562 
00563         if (winbind_env_set()) {
00564                 return NSS_STATUS_NOTFOUND;
00565         }
00566 
00567         if (!request) {
00568                 ZERO_STRUCT(lrequest);
00569                 request = &lrequest;
00570         }
00571         
00572         /* Fill in request and send down pipe */
00573 
00574         init_request(request, req_type);
00575         
00576         if (write_sock(request, sizeof(*request),
00577                        request->flags & WBFLAG_RECURSE, need_priv) == -1) {
00578                 /* Set ENOENT for consistency.  Required by some apps */
00579                 errno = ENOENT;
00580                 
00581                 return NSS_STATUS_UNAVAIL;
00582         }
00583 
00584         if ((request->extra_len != 0) &&
00585             (write_sock(request->extra_data.data, request->extra_len,
00586                         request->flags & WBFLAG_RECURSE, need_priv) == -1)) {
00587                 /* Set ENOENT for consistency.  Required by some apps */
00588                 errno = ENOENT;
00589 
00590                 return NSS_STATUS_UNAVAIL;
00591         }
00592         
00593         return NSS_STATUS_SUCCESS;
00594 }

NSS_STATUS winbindd_get_response ( struct winbindd_response response  ) 

wb_common.c600 行で定義されています。

参照先 errnofree_response()init_response()NSS_STATUS_NOTFOUNDNSS_STATUS_SUCCESSNSS_STATUS_UNAVAILread_reply()winbindd_response::resultWINBINDD_OK.

参照元 winbind_callback()winbindd_priv_request_response()winbindd_request_response().

00601 {
00602         struct winbindd_response lresponse;
00603 
00604         if (!response) {
00605                 ZERO_STRUCT(lresponse);
00606                 response = &lresponse;
00607         }
00608 
00609         init_response(response);
00610 
00611         /* Wait for reply */
00612         if (read_reply(response) == -1) {
00613                 /* Set ENOENT for consistency.  Required by some apps */
00614                 errno = ENOENT;
00615 
00616                 return NSS_STATUS_UNAVAIL;
00617         }
00618 
00619         /* Throw away extra data if client didn't request it */
00620         if (response == &lresponse) {
00621                 free_response(response);
00622         }
00623 
00624         /* Copy reply data from socket */
00625         if (response->result != WINBINDD_OK) {
00626                 return NSS_STATUS_NOTFOUND;
00627         }
00628         
00629         return NSS_STATUS_SUCCESS;
00630 }

NSS_STATUS winbindd_request_response ( int  req_type,
struct winbindd_request request,
struct winbindd_response response 
)

wb_common.c634 行で定義されています。

参照先 NSS_STATUS_SUCCESSNSS_STATUS_UNAVAILstatuswinbindd_get_response()winbindd_send_request().

00637 {
00638         NSS_STATUS status = NSS_STATUS_UNAVAIL;
00639         int count = 0;
00640 
00641         while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) {
00642                 status = winbindd_send_request(req_type, 0, request);
00643                 if (status != NSS_STATUS_SUCCESS) 
00644                         return(status);
00645                 status = winbindd_get_response(response);
00646                 count += 1;
00647         }
00648 
00649         return status;
00650 }

NSS_STATUS winbindd_priv_request_response ( int  req_type,
struct winbindd_request request,
struct winbindd_response response 
)

wb_common.c652 行で定義されています。

参照先 NSS_STATUS_SUCCESSNSS_STATUS_UNAVAILstatuswinbindd_get_response()winbindd_send_request().

参照元 check_winbind_security().

00655 {
00656         NSS_STATUS status = NSS_STATUS_UNAVAIL;
00657         int count = 0;
00658 
00659         while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) {
00660                 status = winbindd_send_request(req_type, 1, request);
00661                 if (status != NSS_STATUS_SUCCESS) 
00662                         return(status);
00663                 status = winbindd_get_response(response);
00664                 count += 1;
00665         }
00666 
00667         return status;
00668 }


変数

int winbindd_fd = -1

wb_common.c35 行で定義されています。

参照元 close_sock()read_sock()wbinfo_ping()winbind_open_pipe_sock()write_sock().

int is_privileged = 0 [static]

wb_common.c36 行で定義されています。

参照元 winbind_open_pipe_sock().


Sambaに対してSat Aug 29 21:23:55 2009に生成されました。  doxygen 1.4.7