Example #1
0
int
cfstring_to_cstring(const CFStringRef val, char **buffer)
{
	CFIndex maxlen = 0;
	int retval = PAM_BUF_ERR;
	
	if (NULL == val || NULL == buffer) {
		openpam_log(PAM_LOG_DEBUG, "NULL argument passed");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}
	
	maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(val), kCFStringEncodingUTF8);
	*buffer = calloc(maxlen + 1, sizeof(char));
	if (NULL == *buffer) {
		openpam_log(PAM_LOG_DEBUG, "malloc() failed");
		retval = PAM_BUF_ERR;
		goto cleanup;
	}
	
	if (CFStringGetCString(val, *buffer, maxlen + 1, kCFStringEncodingUTF8)) {
		retval =  PAM_SUCCESS;
	} else {
		openpam_log(PAM_LOG_DEBUG, "CFStringGetCString failed.");
		free(*buffer);
		*buffer = NULL;
	}
	
cleanup:
	if (PAM_SUCCESS != retval)
		openpam_log(PAM_LOG_ERROR, "failed: %d", retval);
	
	return retval;
}
Example #2
0
int
cstring_to_cfstring(const char *val, CFStringRef *buffer)
{
	int retval = PAM_BUF_ERR;
	
	if (NULL == val || NULL == buffer) {
		openpam_log(PAM_LOG_DEBUG, "NULL argument passed");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}
	
	*buffer = CFStringCreateWithCString(kCFAllocatorDefault, val, kCFStringEncodingUTF8);
	if (NULL == *buffer) {
		openpam_log(PAM_LOG_DEBUG, "CFStringCreateWithCString() failed");
		retval = PAM_BUF_ERR;
		goto cleanup;
	}
	
	retval =  PAM_SUCCESS;
	
cleanup:
	if (PAM_SUCCESS != retval)
		openpam_log(PAM_LOG_ERROR, "failed: %d", retval);
	
	return retval;
}
Example #3
0
static char *
prompt_echo_off(const char *msg, FILE *infp, FILE *outfp, FILE *errfp)
{
	struct termios tattr;
	tcflag_t lflag;
	char *ret;
	int fd;

	fd = fileno(infp);
	if (tcgetattr(fd, &tattr) != 0) {
		openpam_log(PAM_LOG_ERROR, "tcgetattr(): %s", strerror(errno));
		return (NULL);
	}
	lflag = tattr.c_lflag;
	tattr.c_lflag &= ~ECHO;
	if (tcsetattr(fd, TCSAFLUSH, &tattr) != 0) {
		openpam_log(PAM_LOG_ERROR, "tcsetattr(): %s", strerror(errno));
		return (NULL);
	}
	ret = prompt(msg, infp, outfp, errfp);
	tattr.c_lflag = lflag;
	(void)tcsetattr(fd, TCSANOW, &tattr);
	if (ret != NULL)
		fputs("\n", outfp);
	return (ret);
}
Example #4
0
static void *
try_dlopen(const char *modfn, int *error)
{
	void *dlh;
	int fd;

	openpam_log(PAM_LOG_LIBDEBUG, "dlopen(%s)", modfn);
	if ((fd = open(modfn, O_RDONLY)) < 0) {
		if (errno != ENOENT)
			openpam_log(PAM_LOG_ERROR, "%s: %m", modfn);
		return (NULL);
	}
	if (OPENPAM_FEATURE(VERIFY_MODULE_FILE) &&
	    openpam_check_desc_owner_perms(modfn, fd) != 0) {
		close(fd);
		return (NULL);
	}
	if ((dlh = fdlopen(fd, RTLD_NOW)) == NULL) {
		openpam_log(PAM_LOG_ERROR, "%s: %s", modfn, dlerror());
		close(fd);
		errno = 0;
		return (NULL);
	}
	close(fd);
	return (dlh);
}
Example #5
0
int
od_record_check_pwpolicy(ODRecordRef record)
{
	CFDictionaryRef policy = NULL;
	const void *isDisabled;
	const void *newPasswordRequired;
	int retval = PAM_SERVICE_ERR;

	if (NULL == record) {
		openpam_log(PAM_LOG_DEBUG, "NULL argument passed");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}

	if (NULL == (policy = ODRecordCopyPasswordPolicy(kCFAllocatorDefault, record, NULL)) ||
	    NULL == (isDisabled = CFDictionaryGetValue(policy, CFSTR("isDisabled"))) ||
	    !cfboolean_get_value(isDisabled))
		retval = PAM_SUCCESS;
	else
		retval = PAM_PERM_DENIED;
	if (NULL != policy &&
		NULL != (newPasswordRequired = CFDictionaryGetValue(policy, CFSTR("newPasswordRequired"))) &&
	    cfboolean_get_value(newPasswordRequired))
		retval = PAM_NEW_AUTHTOK_REQD;

	if (NULL != policy) {
		CFRelease(policy);
	}

cleanup:
	openpam_log(PAM_LOG_DEBUG, "retval: %d", retval);
	return retval;
}
Example #6
0
int
od_record_create_cstring(pam_handle_t *pamh, ODRecordRef *record, const char *user)
{
	int retval = PAM_SUCCESS;
	CFStringRef cfUser = NULL;

	if (NULL == record || NULL == user) {
		openpam_log(PAM_LOG_DEBUG, "NULL argument passed");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}

	if (PAM_SUCCESS != (retval = cstring_to_cfstring(user, &cfUser)) ||
	    PAM_SUCCESS != (retval = od_record_create(pamh, record, cfUser))) {
		openpam_log(PAM_LOG_DEBUG, "od_record_create() failed");
		goto cleanup;
	}

cleanup:
	if (PAM_SUCCESS != retval) {
		openpam_log(PAM_LOG_ERROR, "failed: %d", retval);
		if (NULL != *record) {
			CFRelease(*record);
		}
	}

	if (NULL != cfUser) {
		CFRelease(cfUser);
	}

	return retval;
}
Example #7
0
int
openpam_straddch(char **str, size_t *size, size_t *len, int ch)
{
	size_t tmpsize;
	char *tmpstr;

	if (*str == NULL) {
		/* initial allocation */
		tmpsize = MIN_STR_SIZE;
		if ((tmpstr = malloc(tmpsize)) == NULL) {
			openpam_log(PAM_LOG_ERROR, "malloc(): %m");
			errno = ENOMEM;
			return (-1);
		}
		*str = tmpstr;
		*size = tmpsize;
		*len = 0;
	} else if (ch != 0 && *len + 1 >= *size) {
		/* additional space required */
		tmpsize = *size * 2;
		if ((tmpstr = realloc(*str, tmpsize)) == NULL) {
			openpam_log(PAM_LOG_ERROR, "realloc(): %m");
			errno = ENOMEM;
			return (-1);
		}
		*size = tmpsize;
		*str = tmpstr;
	}
	if (ch != 0) {
		(*str)[*len] = ch;
		++*len;
	}
	(*str)[*len] = '\0';
	return (0);
}
Example #8
0
/*
 * Attempts to load a private key from the specified file in the specified
 * directory, using the specified passphrase.  If successful, returns a
 * struct pam_ssh_key containing the key and its comment.
 */
static struct pam_ssh_key *
pam_ssh_load_key(const char *dir, const char *kfn, const char *passphrase)
{
	struct pam_ssh_key *psk;
	char fn[PATH_MAX];
	char *comment;
	Key *key;

	if (snprintf(fn, sizeof(fn), "%s/%s", dir, kfn) > (int)sizeof(fn))
		return (NULL);
	comment = NULL;
	key = key_load_private(fn, passphrase, &comment);
	if (key == NULL) {
		openpam_log(PAM_LOG_DEBUG, "failed to load key from %s\n", fn);
		return (NULL);
	}

	openpam_log(PAM_LOG_DEBUG, "loaded '%s' from %s\n", comment, fn);
	if ((psk = malloc(sizeof(*psk))) == NULL) {
		key_free(key);
		free(comment);
		return (NULL);
	}
	psk->key = key;
	psk->comment = comment;
	return (psk);
}
pam_module_t *
openpam_dynamic(const char *path)
{
	const pam_module_t *dlmodule;
	pam_module_t *module;
	const char *prefix, *epath = path;
	char *vpath;
	void *dlh;
	int i, serrno;

	dlh = NULL;

	/* Prepend the standard prefix if not an absolute pathname. */
	if (path[0] != '/')
		prefix = OPENPAM_MODULES_DIR;
	else
		prefix = "";

	/* try versioned module first, then unversioned module */
	if (asprintf(&vpath, "%s/%s.%d", prefix, path, LIB_MAJ) < 0)
		goto err;
	epath = vpath;
	if ((dlh = try_dlopen(vpath)) == NULL && errno == ENOENT) {
		*strrchr(vpath, '.') = '\0';
		dlh = try_dlopen(vpath);
	}
	serrno = errno;
	FREE(vpath);
	errno = serrno;
	if (dlh == NULL)
		goto err;
	if ((module = calloc((size_t)1, sizeof *module)) == NULL)
		goto buf_err;
	if ((module->path = strdup(path)) == NULL)
		goto buf_err;
	module->dlh = dlh;
	dlmodule = dlsym(dlh, "_pam_module");
	for (i = 0; i < PAM_NUM_PRIMITIVES; ++i) {
		module->func[i] = dlmodule ? dlmodule->func[i] :
		    (pam_func_t)dlsym(dlh, pam_sm_func_name[i]);
		if (module->func[i] == NULL)
			openpam_log(PAM_LOG_DEBUG, "%s: %s(): %s",
			    path, pam_sm_func_name[i], dlerror());
	}
	return (module);
buf_err:
	serrno = errno;
	if (dlh != NULL)
		dlclose(dlh);
	FREE(module);
	errno = serrno;
err:
	openpam_log(errno == ENOENT ? PAM_LOG_DEBUG : PAM_LOG_ERROR, "%s: %s",
	    epath, strerror(errno));
	return (NULL);
}
Example #10
0
char *
openpam_readline(FILE *f, int *lineno, size_t *lenp)
{
	char *line;
	size_t len, size;
	int ch;

	if ((line = malloc(size = MIN_LINE_LENGTH)) == NULL) {
		openpam_log(PAM_LOG_ERROR, "malloc(): %m");
		return (NULL);
	}
	len = 0;
	for (;;) {
		ch = fgetc(f);
		/* strip comment */
		if (ch == '#') {
			do {
				ch = fgetc(f);
			} while (ch != EOF && ch != '\n');
		}
		/* eof */
		if (ch == EOF) {
			/* done */
			break;
		}
		/* eol */
		if (ch == '\n') {
			if (lineno != NULL)
				++*lineno;
			/* skip blank lines */
			if (len == 0)
				continue;
			/* continuation */
			if (line[len - 1] == '\\') {
				line[--len] = '\0';
				continue;
			}
			/* done */
			break;
		}
		/* anything else */
		if (openpam_straddch(&line, &size, &len, ch) != 0)
			goto fail;
	}
	if (len == 0)
		goto fail;
	if (lenp != NULL)
		*lenp = len;
	openpam_log(PAM_LOG_LIBDEBUG, "returning '%s'", line);
	return (line);
fail:
	FREE(line);
	return (NULL);
}
Example #11
0
/*
 * Try to load a module from the suggested location.
 */
static pam_module_t *
try_module(const char *modpath)
{
	const pam_module_t *dlmodule;
	pam_module_t *module;
	int i, serrno;

	if ((module = calloc(1, sizeof *module)) == NULL ||
	    (module->path = strdup(modpath)) == NULL ||
	    (module->dlh = try_dlopen(modpath)) == NULL)
		goto err;
	dlmodule = dlsym(module->dlh, "_pam_module");
	for (i = 0; i < PAM_NUM_PRIMITIVES; ++i) {
		if (dlmodule) {
			module->func[i] = dlmodule->func[i];
		} else {
			module->func[i] = (pam_func_t)dlfunc(module->dlh,
			    pam_sm_func_name[i]);
			/*
			 * This openpam_log() call is a major source of
			 * log spam, and the cases that matter are caught
			 * and logged in openpam_dispatch().  This would
			 * be less problematic if dlerror() returned an
			 * error code so we could log an error only when
			 * dlfunc() failed for a reason other than "no
			 * such symbol".
			 */
#if 0
			if (module->func[i] == NULL)
				openpam_log(PAM_LOG_LIBDEBUG, "%s: %s(): %s",
				    modpath, pam_sm_func_name[i], dlerror());
#endif
		}
	}
	return (module);
err:
	serrno = errno;
	if (module != NULL) {
		if (module->dlh != NULL)
			dlclose(module->dlh);
		if (module->path != NULL)
			FREE(module->path);
		FREE(module);
	}
	errno = serrno;
	if (serrno != 0 && serrno != ENOENT)
		openpam_log(PAM_LOG_ERROR, "%s: %m", modpath);
	errno = serrno;
	return (NULL);
}
Example #12
0
int
od_record_check_homedir(ODRecordRef record)
{
	int retval = PAM_SERVICE_ERR;
	CFStringRef tmp = NULL;

	if (NULL == record) {
		openpam_log(PAM_LOG_DEBUG, "NULL argument passed");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}

	retval = od_record_attribute_create_cfstring(record, kODAttributeTypeNFSHomeDirectory, &tmp);
	if (PAM_SUCCESS != retval) {
		openpam_log(PAM_LOG_DEBUG, "od_record_attribute_create_cfstring() failed");
		goto cleanup;
	}

	/* Allow NULL home directories */
	if (NULL == tmp) {
		retval = PAM_SUCCESS;
		goto cleanup;
	}

	/* Do not allow login with '/dev/null' home */
	if (kCFCompareEqualTo == CFStringCompare(tmp, CFSTR("/dev/null"), 0)) {
		openpam_log(PAM_LOG_DEBUG, "home directory is /dev/null");
		retval = PAM_PERM_DENIED;
		goto cleanup;
	}

	if (kCFCompareEqualTo == CFStringCompare(tmp, CFSTR("99"), 0)) {
		openpam_log(PAM_LOG_DEBUG, "home directory is 99");
		retval = PAM_PERM_DENIED;
		goto cleanup;
	}

	retval = PAM_SUCCESS;

cleanup:
	if (PAM_SUCCESS != retval)
		openpam_log(PAM_LOG_ERROR, "failed: %d", retval);

	if (NULL != tmp) {
		CFRelease(tmp);
	}

	return retval;
}
Example #13
0
int
od_string_from_record(ODRecordRef record, CFStringRef attrib,  char **out)
{
	int retval = PAM_SERVICE_ERR;
	CFStringRef val = NULL;
	
	if (NULL == record) {
		openpam_log(PAM_LOG_DEBUG, "%s - NULL ODRecord passed.", __func__);
		goto cleanup;
	}
	
	retval = od_record_attribute_create_cfstring(record, attrib, &val);
	if (PAM_SUCCESS != retval) {
		goto cleanup;
	}
	
	if (val)
		retval = cfstring_to_cstring(val, out);
	
cleanup:
	if (val)
		CFRelease(val);
	
	return retval;
}
Example #14
0
int
pam_start(const char *service,
	const char *user,
	const struct pam_conv *pam_conv,
	pam_handle_t **pamh)
{
	char hostname[HOST_NAME_MAX + 1];
	struct pam_handle *ph;
	int r;

	ENTER();
	if ((ph = calloc(1, sizeof *ph)) == NULL)
		RETURNC(PAM_BUF_ERR);
	if ((r = pam_set_item(ph, PAM_SERVICE, service)) != PAM_SUCCESS)
		goto fail;
	if (gethostname(hostname, sizeof hostname) != 0)
		strlcpy(hostname, "localhost", sizeof hostname);
	if ((r = pam_set_item(ph, PAM_HOST, hostname)) != PAM_SUCCESS)
		goto fail;
	if ((r = pam_set_item(ph, PAM_USER, user)) != PAM_SUCCESS)
		goto fail;
	if ((r = pam_set_item(ph, PAM_CONV, pam_conv)) != PAM_SUCCESS)
		goto fail;
	if ((r = openpam_configure(ph, service)) != PAM_SUCCESS)
		goto fail;
	*pamh = ph;
	openpam_log(PAM_LOG_DEBUG, "pam_start(\"%s\") succeeded", service);
	RETURNC(PAM_SUCCESS);
fail:
	pam_end(ph, r);
	RETURNC(r);
}
Example #15
0
int
pam_vprompt(const pam_handle_t *pamh,
	int style,
	char **resp,
	const char *fmt,
	va_list ap)
{
	char msgbuf[PAM_MAX_MSG_SIZE];
	struct pam_message msg;
	const struct pam_message *msgp;
	struct pam_response *rsp;
	const struct pam_conv *conv;
	const void *convp;
	int r;

	ENTER();
	r = pam_get_item(pamh, PAM_CONV, &convp);
	if (r != PAM_SUCCESS)
		RETURNC(r);
	conv = convp;
	if (conv == NULL || conv->conv == NULL) {
		openpam_log(PAM_LOG_ERROR, "no conversation function");
		RETURNC(PAM_SYSTEM_ERR);
	}
	vsnprintf(msgbuf, (size_t)PAM_MAX_MSG_SIZE, fmt, ap);
	msg.msg_style = style;
	msg.msg = msgbuf;
	msgp = &msg;
	rsp = NULL;
	r = (conv->conv)(1, &msgp, &rsp, conv->appdata_ptr);
	*resp = rsp == NULL ? NULL : rsp->resp;
	FREE(rsp);
	RETURNC(r);
	/*NOTREACHED*/
}
Example #16
0
int
openpam_configure(pam_handle_t *pamh,
	const char *service)
{
	pam_facility_t fclt;
	int serrno;

	ENTERS(service);
	if (!valid_service_name(service)) {
		openpam_log(PAM_LOG_ERROR, "invalid service name");
		RETURNC(PAM_SYSTEM_ERR);
	}
	if (openpam_load_chain(pamh, service, PAM_FACILITY_ANY) < 0) {
		if (errno != ENOENT)
			goto load_err;
	}
	for (fclt = 0; fclt < PAM_NUM_FACILITIES; ++fclt) {
		if (pamh->chains[fclt] != NULL)
			continue;
		if (openpam_load_chain(pamh, PAM_OTHER, fclt) < 0)
			goto load_err;
	}
	RETURNC(PAM_SUCCESS);
load_err:
	serrno = errno;
	openpam_clear_chains(pamh->chains);
	errno = serrno;
	RETURNC(PAM_SYSTEM_ERR);
}
Example #17
0
int
openpam_configure(pam_handle_t *pamh,
	const char *service)
{
	pam_facility_t fclt;
	int serrno;

	ENTERS(service);
	if (!valid_service_name(service)) {
		openpam_log(PAM_LOG_ERROR, "invalid service name");
		RETURNC(PAM_SYSTEM_ERR);
	}
	if (openpam_load_chain(pamh, service, PAM_FACILITY_ANY) < 0)
		goto load_err;
	for (fclt = 0; fclt < PAM_NUM_FACILITIES; ++fclt) {
		if (pamh->chains[fclt] != NULL)
			continue;
		if (openpam_load_chain(pamh, PAM_OTHER, fclt) < 0)
			goto load_err;
	}
#ifdef __NetBSD__
	/*
	 * On NetBSD we require the AUTH chain to have a binding
	 * or a required module.
	 */
	{
		pam_chain_t *this = pamh->chains[PAM_AUTH];
		for (; this != NULL; this = this->next)
			if (this->flag == PAM_BINDING ||
			    this->flag == PAM_REQUIRED)
				break;
		if (this == NULL) {
			openpam_log(PAM_LOG_ERROR,
			    "No required or binding component "
			    "in service %s, facility %s",
			    service, pam_facility_name[PAM_AUTH]);
			goto load_err;
		}
	}
#endif
	RETURNC(PAM_SUCCESS);
load_err:
	serrno = errno;
	openpam_clear_chains(pamh->chains);
	errno = serrno;
	RETURNC(PAM_SYSTEM_ERR);
}
int
openpam_borrow_cred(pam_handle_t *pamh,
	const struct passwd *pwd)
{
	struct pam_saved_cred *scred;
	const void *scredp;
	int r;

	ENTERI(pwd->pw_uid);
	r = pam_get_data(pamh, PAM_SAVED_CRED, &scredp);
	if (r == PAM_SUCCESS && scredp != NULL) {
		openpam_log(PAM_LOG_DEBUG,
		    "already operating under borrowed credentials");
		RETURNC(PAM_SYSTEM_ERR);
	}
	if (geteuid() != 0 && geteuid() != pwd->pw_uid) {
		openpam_log(PAM_LOG_DEBUG, "called with non-zero euid: %d",
		    (int)geteuid());
		RETURNC(PAM_PERM_DENIED);
	}
	scred = calloc((size_t)1, sizeof *scred);
	if (scred == NULL)
		RETURNC(PAM_BUF_ERR);
	scred->euid = geteuid();
	scred->egid = getegid();
	r = getgroups(NGROUPS_MAX, scred->groups);
	if (r < 0) {
		FREE(scred);
		RETURNC(PAM_SYSTEM_ERR);
	}
	scred->ngroups = r;
	r = pam_set_data(pamh, PAM_SAVED_CRED, scred, &openpam_free_data);
	if (r != PAM_SUCCESS) {
		FREE(scred);
		RETURNC(r);
	}
	if (geteuid() == pwd->pw_uid)
		RETURNC(PAM_SUCCESS);
	if (initgroups(pwd->pw_name, pwd->pw_gid) < 0 ||
	      setegid(pwd->pw_gid) < 0 || seteuid(pwd->pw_uid) < 0) {
		openpam_restore_cred(pamh);
		RETURNC(PAM_SYSTEM_ERR);
	}
	RETURNC(PAM_SUCCESS);
	/*NOTREACHED*/
}
static void
openpam_check_error_code(int primitive, int r)
{
	/* common error codes */
	if (r == PAM_SUCCESS ||
	    r == PAM_SYSTEM_ERR ||
	    r == PAM_SERVICE_ERR ||
	    r == PAM_BUF_ERR ||
	    r == PAM_CONV_ERR ||
	    r == PAM_PERM_DENIED ||
	    r == PAM_ABORT)
		return;

	/* specific error codes */
	switch (primitive) {
	case PAM_SM_AUTHENTICATE:
		if (r == PAM_AUTH_ERR ||
		    r == PAM_CRED_INSUFFICIENT ||
		    r == PAM_AUTHINFO_UNAVAIL ||
		    r == PAM_USER_UNKNOWN ||
		    r == PAM_MAXTRIES)
			return;
		break;
	case PAM_SM_SETCRED:
		if (r == PAM_CRED_UNAVAIL ||
		    r == PAM_CRED_EXPIRED ||
		    r == PAM_USER_UNKNOWN ||
		    r == PAM_CRED_ERR)
			return;
		break;
	case PAM_SM_ACCT_MGMT:
		if (r == PAM_USER_UNKNOWN ||
		    r == PAM_AUTH_ERR ||
		    r == PAM_NEW_AUTHTOK_REQD ||
		    r == PAM_ACCT_EXPIRED)
			return;
		break;
	case PAM_SM_OPEN_SESSION:
	case PAM_SM_CLOSE_SESSION:
		if (r == PAM_SESSION_ERR)
			return;
		break;
	case PAM_SM_CHAUTHTOK:
		if (r == PAM_PERM_DENIED ||
		    r == PAM_AUTHTOK_ERR ||
		    r == PAM_AUTHTOK_RECOVERY_ERR ||
		    r == PAM_AUTHTOK_LOCK_BUSY ||
		    r == PAM_AUTHTOK_DISABLE_AGING ||
		    r == PAM_TRY_AGAIN)
			return;
		break;
	}

	openpam_log(PAM_LOG_ERROR, "%s(): unexpected return value %d",
	    pam_sm_func_name[primitive], r);
}
Example #20
0
static void *
try_dlopen(const char *modfn)
{
	int check_module_file;
	void *dlh;

	openpam_log(PAM_LOG_LIBDEBUG, "dlopen(%s)", modfn);
	openpam_get_feature(OPENPAM_VERIFY_MODULE_FILE,
	    &check_module_file);
	if (check_module_file &&
	    openpam_check_path_owner_perms(modfn) != 0)
		return (NULL);
	if ((dlh = dlopen(modfn, RTLD_NOW)) == NULL) {
		openpam_log(PAM_LOG_ERROR, "%s: %s", modfn, dlerror());
		errno = 0;
		return (NULL);
	}
	return (dlh);
}
Example #21
0
/*
 * Attempts to load a private key from the specified file in the specified
 * directory, using the specified passphrase.  If successful, returns a
 * struct pam_ssh_key containing the key and its comment.
 */
static struct pam_ssh_key *
pam_ssh_load_key(const char *dir, const char *kfn, const char *passphrase,
    int nullok)
{
	struct pam_ssh_key *psk;
	char fn[PATH_MAX];
	char *comment;
	Key *key;

	if (snprintf(fn, sizeof(fn), "%s/%s", dir, kfn) > (int)sizeof(fn))
		return (NULL);
	comment = NULL;
	/*
	 * If the key is unencrypted, OpenSSL ignores the passphrase, so
	 * it will seem like the user typed in the right one.  This allows
	 * a user to circumvent nullok by providing a dummy passphrase.
	 * Verify that the key really *is* encrypted by trying to load it
	 * with an empty passphrase, and if the key is not encrypted,
	 * accept only an empty passphrase.
	 */
	key = key_load_private(fn, "", &comment);
	if (key != NULL && !(*passphrase == '\0' && nullok)) {
		key_free(key);
		return (NULL);
	}
	if (key == NULL)
		key = key_load_private(fn, passphrase, &comment);
	if (key == NULL) {
		openpam_log(PAM_LOG_DEBUG, "failed to load key from %s", fn);
		return (NULL);
	}

	openpam_log(PAM_LOG_DEBUG, "loaded '%s' from %s", comment, fn);
	if ((psk = malloc(sizeof(*psk))) == NULL) {
		key_free(key);
		free(comment);
		return (NULL);
	}
	psk->key = key;
	psk->comment = comment;
	return (psk);
}
Example #22
0
static void
openpam_release_module(pam_module_t *module)
{
	if (module == NULL)
		return;
	if (module->dlh == NULL)
		/* static module */
		return;
	dlclose(module->dlh);
	openpam_log(PAM_LOG_DEBUG, "releasing %s", module->path);
	FREE(module->path);
	FREE(module);
}
Example #23
0
PAM_EXTERN
int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
			,const char **argv)
{
    int retval = PAM_AUTH_ERR;

    if (getuid() == 0)
	retval = PAM_SUCCESS;

	openpam_log(PAM_LOG_DEBUG, "authentication %s", retval==PAM_SUCCESS ? "succeeded":"failed" );

    return retval;
}
Example #24
0
int
od_record_check_shell(ODRecordRef record)
{
	int retval = PAM_PERM_DENIED;
	CFStringRef cfstr = NULL;

	if (NULL == record) {
		openpam_log(PAM_LOG_DEBUG, "NULL argument passed");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}

	retval = od_record_attribute_create_cfstring(record, kODAttributeTypeUserShell, &cfstr);
	if (PAM_SUCCESS != retval) {
		openpam_log(PAM_LOG_DEBUG, "od_record_attribute_create_cfstring() failed");
		goto cleanup;
	}

	if (NULL == cfstr) {
		retval = PAM_SUCCESS;
		goto cleanup;
	}

	if (CFStringCompare(cfstr, CFSTR("/usr/bin/false"), 0) == kCFCompareEqualTo) {
		openpam_log(PAM_LOG_DEBUG, "user shell is /bin/false");
		retval = PAM_PERM_DENIED;
	}

cleanup:
	if (PAM_SUCCESS != retval)
		openpam_log(PAM_LOG_ERROR, "failed: %d", retval);

	if (NULL != cfstr) {
		CFRelease(cfstr);
	}

	return retval;
}
Example #25
0
pam_module_t *
openpam_load_module(const char *path)
{
	pam_module_t *module;

	module = openpam_dynamic(path);
	openpam_log(PAM_LOG_DEBUG, "%s dynamic %s",
	    (module == NULL) ? "no" : "using", path);

#ifdef OPENPAM_STATIC_MODULES
	/* look for a static module */
	if (module == NULL && strchr(path, '/') == NULL) {
		module = openpam_static(path);
		openpam_log(PAM_LOG_DEBUG, "%s static %s",
		    (module == NULL) ? "no" : "using", path);
	}
#endif
	if (module == NULL) {
		openpam_log(PAM_LOG_ERROR, "no %s found", path);
		return (NULL);
	}
	return (module);
}
Example #26
0
/* Can return NULL */
int
od_record_attribute_create_cstring(ODRecordRef record, CFStringRef attrib,  char **out)
{
	int retval = PAM_SERVICE_ERR;
	CFStringRef val = NULL;

	if (NULL == record || NULL == attrib || NULL == out) {
		openpam_log(PAM_LOG_DEBUG, "NULL argument passed");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}

	retval = od_record_attribute_create_cfstring(record, attrib, &val);
	if (PAM_SUCCESS != retval) {
		openpam_log(PAM_LOG_DEBUG, "od_record_attribute_create_cfstring() failed");
		goto cleanup;
	}

	if (NULL != val) {
		retval = cfstring_to_cstring(val, out);
		if (PAM_SUCCESS != retval) {
			openpam_log(PAM_LOG_DEBUG, "cfstring_to_cstring() failed");
			goto cleanup;
		}
	}

cleanup:
	if (PAM_SUCCESS != retval) {
		free(out);
	}

	if (NULL != val) {
		CFRelease(val);
	}

	return retval;
}
Example #27
0
int
od_extract_home(pam_handle_t *pamh, const char *username, char **server_URL, char **path, char **homedir)
{
	int retval = PAM_SERVICE_ERR;
	char *tmp = NULL;
	ODRecordRef record = NULL;
	
	retval = od_record_create_cstring(pamh, &record, username);
	if (PAM_SUCCESS != retval) {
		goto cleanup;
	}
	
	retval = od_string_from_record(record, kODAttributeTypeHomeDirectory, &tmp);
	if (retval) {
		openpam_log(PAM_LOG_DEBUG, "%s - get kODAttributeTypeHomeDirectory  : %d",
			    __func__, retval);
		goto cleanup;
	}
	extract_homemount(tmp, server_URL, path);
	openpam_log(PAM_LOG_DEBUG, "%s - Server URL   : %s", __func__, *server_URL);
	openpam_log(PAM_LOG_DEBUG, "%s - Path to mount: %s", __func__, *path);
	
	retval = od_string_from_record(record, kODAttributeTypeNFSHomeDirectory, homedir);
	openpam_log(PAM_LOG_DEBUG, "%s - Home dir     : %s", __func__, *homedir);
	if (retval)
		goto cleanup;
	
	retval = PAM_SUCCESS;
	
cleanup:
	if (tmp)
		free(tmp);
	if (record)
		CFRelease(record);
	
	return retval;
}
/*
 * Locates the policy file for a given service and reads the given chains
 * from it.
 */
static int
openpam_load_chain(pam_handle_t *pamh,
	const char *service,
	pam_facility_t facility)
{
	const char **path;
	char *filename;
	size_t len;
	int r;

	/* don't allow to escape from policy_path */
	if (strchr(service, '/')) {
		openpam_log(PAM_LOG_ERROR, "invalid service name: %s",
		    service);
		return (-PAM_SYSTEM_ERR);
	}

	for (path = openpam_policy_path; *path != NULL; ++path) {
		len = strlen(*path);
		if ((*path)[len - 1] == '/') {
			if (asprintf(&filename, "%s%s", *path, service) < 0) {
				openpam_log(PAM_LOG_ERROR, "asprintf(): %m");
				return (-PAM_BUF_ERR);
			}
			r = openpam_read_chain(pamh, service, facility,
			    filename, pam_d_style);
			FREE(filename);
		} else {
			r = openpam_read_chain(pamh, service, facility,
			    *path, pam_conf_style);
		}
		if (r != 0)
			return (r);
	}
	return (0);
}
Example #29
0
/*
 * Read the specified chains from the specified file.
 *
 * Returns 0 if the file exists but does not contain any matching lines.
 *
 * Returns -1 and sets errno to ENOENT if the file does not exist.
 *
 * Returns -1 and sets errno to some other non-zero value if the file
 * exists but is unsafe or unreadable, or an I/O error occurs.
 */
static int
openpam_load_file(pam_handle_t *pamh,
	const char *service,
	pam_facility_t facility,
	const char *filename,
	openpam_style_t style)
{
	FILE *f;
	int ret, serrno;

	/* attempt to open the file */
	if ((f = fopen(filename, "r")) == NULL) {
		serrno = errno;
		openpam_log(errno == ENOENT ? PAM_LOG_DEBUG : PAM_LOG_ERROR,
		    "%s: %m", filename);
		errno = serrno;
		RETURNN(-1);
	} else {
		openpam_log(PAM_LOG_DEBUG, "found %s", filename);
	}

	/* verify type, ownership and permissions */
	if (OPENPAM_FEATURE(VERIFY_POLICY_FILE) &&
	    openpam_check_desc_owner_perms(filename, fileno(f)) != 0) {
		/* already logged the cause */
		serrno = errno;
		fclose(f);
		errno = serrno;
		RETURNN(-1);
	}

	/* parse the file */
	ret = openpam_parse_chain(pamh, service, facility,
	    f, filename, style);
	RETURNN(ret);
}
Example #30
0
int
od_record_check_authauthority(ODRecordRef record)
{
	int retval = PAM_PERM_DENIED;
	CFStringRef authauth = NULL;

	if (NULL == record) {
		openpam_log(PAM_LOG_DEBUG, "NULL argument passed");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}

	retval = od_record_attribute_create_cfstring(record, kODAttributeTypeAuthenticationAuthority, &authauth);
	if (PAM_SUCCESS != retval) {
		openpam_log(PAM_LOG_DEBUG, "od_record_attribute_create_cfstring() failed");
		goto cleanup;
	}
	if (NULL == authauth) {
		retval = PAM_SUCCESS;
		goto cleanup;
	}
	if (!CFStringHasPrefix(authauth, CFSTR(kDSValueAuthAuthorityDisabledUser))) {
		retval = PAM_SUCCESS;
	}

cleanup:
	if (PAM_SUCCESS != retval) {
		openpam_log(PAM_LOG_ERROR, "failed: %d", retval);
	}

	if (authauth) {
		CFRelease(authauth);
	}

	return retval;
}