static bool ask_winbind(const char *realm, char **dcname) { NSS_STATUS status; struct winbindd_request request; struct winbindd_response response; ZERO_STRUCT(request); ZERO_STRUCT(response); request.flags = 0x40020600; /* DS_KDC_REQUIRED | DS_IS_DNS_NAME | DS_RETURN_DNS_NAME | DS_IP_REQUIRED */ strncpy(request.domain_name, realm, sizeof(request.domain_name)-1); status = winbindd_request_response(WINBINDD_DSGETDCNAME, &request, &response); if (status != NSS_STATUS_SUCCESS) { #ifdef DEBUG_KRB5 fprintf(stderr,"[%5u]: smb_krb5_locator_lookup: failed with: %s\n", (unsigned int)getpid(), nss_err_str(status)); #endif return false; } *dcname = strdup(response.data.dc_name); if (!*dcname) { return false; } return true; }
NSS_STATUS _nss_winbind_endgrent(void) { NSS_STATUS ret; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: endgrent\n", getpid()); #endif #if HAVE_PTHREAD pthread_mutex_lock(&winbind_nss_mutex); #endif if (num_gr_cache > 0) { ndx_gr_cache = num_gr_cache = 0; winbindd_free_response(&getgrent_response); } ret = winbindd_request_response(NULL, WINBINDD_ENDGRENT, NULL, NULL); #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(), nss_err_str(ret), ret); #endif #if HAVE_PTHREAD pthread_mutex_unlock(&winbind_nss_mutex); #endif return ret; }
_PUBLIC_ NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop) { NSS_STATUS ret; static struct winbindd_response response; struct winbindd_request request; static int keep_response=0; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getpwuid %d\n", getpid(), (unsigned int)uid); #endif /* If our static buffer needs to be expanded we are called again */ if (!keep_response) { /* Call for the first time */ ZERO_STRUCT(response); ZERO_STRUCT(request); request.data.uid = uid; ret = winbindd_request(WINBINDD_GETPWUID, &request, &response); if (ret == NSS_STATUS_SUCCESS) { ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { keep_response = True; *errnop = errno = ERANGE; goto done; } } } else { /* We've been called again */ ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { keep_response = True; *errnop = errno = ERANGE; goto done; } keep_response = False; *errnop = errno = 0; } free_response(&response); done: #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(), (unsigned int)uid, nss_err_str(ret), ret); #endif return ret; }
/* * set up the slot/handle/trust things that NSS needs */ static bool prepare_nss_import(PK11SlotInfo **slot, CERTCertDBHandle **handle) { /* * possibly need to handle passworded db case here */ *slot = PK11_GetInternalKeySlot(); if (*slot == NULL) { DBG(DBG_X509, DBG_log("NSS PK11_GetInternalKeySlot error: %s", nss_err_str(PORT_GetError()))); return FALSE; } *handle = CERT_GetDefaultCertDB(); if (*handle == NULL) { DBG(DBG_X509, DBG_log("NSS error getting DB handle: %s", nss_err_str(PORT_GetError()))); return FALSE; } return TRUE; }
/* * Does a temporary import, which decodes the entire chain and allows * CERT_VerifyCert to verify the chain when passed the end certificate */ static int crt_tmp_import(CERTCertDBHandle *handle, CERTCertificate ***chain, SECItem *ders, int der_cnt) { if (der_cnt < 1) { DBG(DBG_X509, DBG_log("nothing to decode")); return 0; } SECItem **derlist = PORT_Alloc(sizeof(SECItem *) * der_cnt); int i; int nonroot = 0; for (i = 0; i < der_cnt; i++) { if (!CERT_IsRootDERCert(&ders[i])) derlist[nonroot++] = &ders[i]; } int fin_count = 0; if (nonroot < 1) { DBG(DBG_X509, DBG_log("nothing to decode")); } else { SECStatus rv = CERT_ImportCerts(handle, 0, nonroot, derlist, chain, PR_FALSE, PR_FALSE, NULL); if (rv != SECSuccess || *chain == NULL) { DBG(DBG_X509, DBG_log("NSS error decoding certs: %s", nss_err_str(PORT_GetError()))); } else { CERTCertificate **cc; for (cc = *chain; fin_count < nonroot && *cc != NULL; cc++) { DBG(DBG_X509, DBG_log("decoded %s", (*cc)->subjectName)); fin_count++; } } } PORT_Free(derlist); return fin_count; }
static int nss_err_to_revfail(CERTVerifyLogNode *node) { int ret = VERIFY_RET_FAIL; if (node == NULL || node->cert == NULL) { return ret; } loglog(RC_LOG_SERIOUS, "Certificate %s failed verification", node->cert->subjectName); loglog(RC_LOG_SERIOUS, "ERROR: %s", nss_err_str(node->error)); if (node->error == SEC_ERROR_REVOKED_CERTIFICATE) { ret = VERIFY_RET_REVOKED; } return ret; }
_PUBLIC_ NSS_STATUS _nss_winbind_endgrent(void) { NSS_STATUS ret; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: endgrent\n", getpid()); #endif if (num_gr_cache > 0) { ndx_gr_cache = num_gr_cache = 0; free_response(&getgrent_response); } ret = winbindd_request(WINBINDD_ENDGRENT, NULL, NULL); #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(), nss_err_str(ret), ret); #endif return ret; }
NSS_STATUS _nss_winbind_setpwent(void) { NSS_STATUS ret; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: setpwent\n", getpid()); #endif if (num_pw_cache > 0) { ndx_pw_cache = num_pw_cache = 0; free_response(&getpwent_response); } ret = winbindd_request_response(WINBINDD_SETPWENT, NULL, NULL); #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: setpwent returns %s (%d)\n", getpid(), nss_err_str(ret), ret); #endif return ret; }
NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, size_t buflen, int *errnop) { NSS_STATUS ret; static struct winbindd_response response; struct winbindd_request request; static int keep_response; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getgrgid %d\n", getpid(), gid); #endif #if HAVE_PTHREAD pthread_mutex_lock(&winbind_nss_mutex); #endif /* If our static buffer needs to be expanded we are called again */ /* Or if the stored response group name differs from the request. */ if (!keep_response || gid != response.data.gr.gr_gid) { /* Call for the first time */ ZERO_STRUCT(request); ZERO_STRUCT(response); request.data.gid = gid; ret = winbindd_request_response(NULL, WINBINDD_GETGRGID, &request, &response); if (ret == NSS_STATUS_SUCCESS) { ret = fill_grent(result, &response.data.gr, (char *)response.extra_data.data, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { keep_response = true; *errnop = errno = ERANGE; goto done; } } } else { /* We've been called again */ ret = fill_grent(result, &response.data.gr, (char *)response.extra_data.data, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { keep_response = true; *errnop = errno = ERANGE; goto done; } keep_response = false; *errnop = 0; } winbindd_free_response(&response); done: #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(), (unsigned int)gid, nss_err_str(ret), ret); #endif #if HAVE_PTHREAD pthread_mutex_unlock(&winbind_nss_mutex); #endif return ret; }
static NSS_STATUS winbind_getgrent(enum winbindd_cmd cmd, struct group *result, char *buffer, size_t buflen, int *errnop) { NSS_STATUS ret; static struct winbindd_request request; static int called_again; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getgrent\n", getpid()); #endif #if HAVE_PTHREAD pthread_mutex_lock(&winbind_nss_mutex); #endif /* Return an entry from the cache if we have one, or if we are called again because we exceeded our static buffer. */ if ((ndx_gr_cache < num_gr_cache) || called_again) { goto return_result; } /* Else call winbindd to get a bunch of entries */ if (num_gr_cache > 0) { winbindd_free_response(&getgrent_response); } ZERO_STRUCT(request); ZERO_STRUCT(getgrent_response); request.data.num_entries = MAX_GETGRENT_USERS; ret = winbindd_request_response(NULL, cmd, &request, &getgrent_response); if (ret == NSS_STATUS_SUCCESS) { struct winbindd_gr *gr_cache; int mem_ofs; /* Fill cache */ ndx_gr_cache = 0; num_gr_cache = getgrent_response.data.num_entries; /* Return a result */ return_result: gr_cache = (struct winbindd_gr *) getgrent_response.extra_data.data; /* Check data is valid */ if (gr_cache == NULL) { ret = NSS_STATUS_NOTFOUND; goto done; } /* Fill group membership. The offset into the extra data for the group membership is the reported offset plus the size of all the winbindd_gr records returned. */ mem_ofs = gr_cache[ndx_gr_cache].gr_mem_ofs + num_gr_cache * sizeof(struct winbindd_gr); ret = fill_grent(result, &gr_cache[ndx_gr_cache], ((char *)getgrent_response.extra_data.data)+mem_ofs, &buffer, &buflen); /* Out of memory - try again */ if (ret == NSS_STATUS_TRYAGAIN) { called_again = true; *errnop = errno = ERANGE; goto done; } *errnop = 0; called_again = false; ndx_gr_cache++; /* If we've finished with this lot of results free cache */ if (ndx_gr_cache == num_gr_cache) { ndx_gr_cache = num_gr_cache = 0; winbindd_free_response(&getgrent_response); } } done: #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getgrent returns %s (%d)\n", getpid(), nss_err_str(ret), ret); #endif #if HAVE_PTHREAD pthread_mutex_unlock(&winbind_nss_mutex); #endif return ret; }
/* Return passwd struct from username */ NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer, size_t buflen, int *errnop) { NSS_STATUS ret; static struct winbindd_response response; struct winbindd_request request; static int keep_response; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getpwnam_r %s\n", getpid(), name); #endif #if HAVE_PTHREAD pthread_mutex_lock(&winbind_nss_mutex); #endif /* If our static buffer needs to be expanded we are called again */ if (!keep_response || strcmp(name,response.data.pw.pw_name) != 0) { /* Call for the first time */ ZERO_STRUCT(response); ZERO_STRUCT(request); strncpy(request.data.username, name, sizeof(request.data.username) - 1); request.data.username [sizeof(request.data.username) - 1] = '\0'; ret = winbindd_request_response(NULL, WINBINDD_GETPWNAM, &request, &response); if (ret == NSS_STATUS_SUCCESS) { ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { keep_response = true; *errnop = errno = ERANGE; goto done; } } } else { /* We've been called again */ ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { keep_response = true; *errnop = errno = ERANGE; goto done; } keep_response = false; *errnop = errno = 0; } winbindd_free_response(&response); done: #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(), name, nss_err_str(ret), ret); #endif #if HAVE_PTHREAD pthread_mutex_unlock(&winbind_nss_mutex); #endif return ret; }
NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) { NSS_STATUS ret; struct winbindd_request request; static int called_again; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getpwent\n", getpid()); #endif #if HAVE_PTHREAD pthread_mutex_lock(&winbind_nss_mutex); #endif /* Return an entry from the cache if we have one, or if we are called again because we exceeded our static buffer. */ if ((ndx_pw_cache < num_pw_cache) || called_again) { goto return_result; } /* Else call winbindd to get a bunch of entries */ if (num_pw_cache > 0) { winbindd_free_response(&getpwent_response); } ZERO_STRUCT(request); ZERO_STRUCT(getpwent_response); request.data.num_entries = MAX_GETPWENT_USERS; ret = winbindd_request_response(NULL, WINBINDD_GETPWENT, &request, &getpwent_response); if (ret == NSS_STATUS_SUCCESS) { struct winbindd_pw *pw_cache; /* Fill cache */ ndx_pw_cache = 0; num_pw_cache = getpwent_response.data.num_entries; /* Return a result */ return_result: pw_cache = (struct winbindd_pw *) getpwent_response.extra_data.data; /* Check data is valid */ if (pw_cache == NULL) { ret = NSS_STATUS_NOTFOUND; goto done; } ret = fill_pwent(result, &pw_cache[ndx_pw_cache], &buffer, &buflen); /* Out of memory - try again */ if (ret == NSS_STATUS_TRYAGAIN) { called_again = true; *errnop = errno = ERANGE; goto done; } *errnop = errno = 0; called_again = false; ndx_pw_cache++; /* If we've finished with this lot of results free cache */ if (ndx_pw_cache == num_pw_cache) { ndx_pw_cache = num_pw_cache = 0; winbindd_free_response(&getpwent_response); } } done: #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getpwent returns %s (%d)\n", getpid(), nss_err_str(ret), ret); #endif #if HAVE_PTHREAD pthread_mutex_unlock(&winbind_nss_mutex); #endif return ret; }
NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop) { NSS_STATUS ret; struct winbindd_request request; struct winbindd_response response; int i; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: initgroups %s (%d)\n", getpid(), user, group); #endif #if HAVE_PTHREAD pthread_mutex_lock(&winbind_nss_mutex); #endif ZERO_STRUCT(request); ZERO_STRUCT(response); strncpy(request.data.username, user, sizeof(request.data.username) - 1); ret = winbindd_request_response(NULL, WINBINDD_GETGROUPS, &request, &response); if (ret == NSS_STATUS_SUCCESS) { int num_gids = response.data.num_entries; gid_t *gid_list = (gid_t *)response.extra_data.data; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS " "and %d gids\n", getpid(), user, num_gids); #endif if (gid_list == NULL) { ret = NSS_STATUS_NOTFOUND; goto done; } /* Copy group list to client */ for (i = 0; i < num_gids; i++) { #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: initgroups %s (%d): " "processing gid %d \n", getpid(), user, group, gid_list[i]); #endif /* Skip primary group */ if (gid_list[i] == group) { continue; } /* Skip groups without a mapping */ if (gid_list[i] == (uid_t)-1) { continue; } /* Filled buffer ? If so, resize. */ if (*start == *size) { long int newsize; gid_t *newgroups; newsize = 2 * (*size); if (limit > 0) { if (*size == limit) { goto done; } if (newsize > limit) { newsize = limit; } } newgroups = (gid_t *) realloc((*groups), newsize * sizeof(**groups)); if (!newgroups) { *errnop = ENOMEM; ret = NSS_STATUS_NOTFOUND; goto done; } *groups = newgroups; *size = newsize; } /* Add to buffer */ (*groups)[*start] = gid_list[i]; *start += 1; } } /* Back to your regularly scheduled programming */ done: #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: initgroups %s returns %s (%d)\n", getpid(), user, nss_err_str(ret), ret); #endif #if HAVE_PTHREAD pthread_mutex_unlock(&winbind_nss_mutex); #endif return ret; }
NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result, char *buffer, size_t buflen, int *errnop) { NSS_STATUS ret; static struct winbindd_response response; struct winbindd_request request; static int keep_response; #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getgrnam %s\n", getpid(), name); #endif /* If our static buffer needs to be expanded we are called again */ if (!keep_response) { /* Call for the first time */ ZERO_STRUCT(request); ZERO_STRUCT(response); strncpy(request.data.groupname, name, sizeof(request.data.groupname)); request.data.groupname [sizeof(request.data.groupname) - 1] = '\0'; ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response); if (ret == NSS_STATUS_SUCCESS) { ret = fill_grent(result, &response.data.gr, (char *)response.extra_data.data, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { keep_response = True; *errnop = errno = ERANGE; goto done; } } } else { /* We've been called again */ ret = fill_grent(result, &response.data.gr, (char *)response.extra_data.data, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { keep_response = True; *errnop = errno = ERANGE; goto done; } keep_response = False; *errnop = 0; } free_response(&response); done: #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(), name, nss_err_str(ret), ret); #endif return ret; }