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;
}
Пример #2
0
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;
}
Пример #3
0
_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;
}
Пример #4
0
/*
 * 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;
}
Пример #5
0
/*
 * 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;
}
Пример #6
0
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;
}
Пример #7
0
_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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
0
/* 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;
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
0
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;
}