diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/passwdutil/nss_attr.c | |
download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/passwdutil/nss_attr.c')
-rw-r--r-- | usr/src/lib/passwdutil/nss_attr.c | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/usr/src/lib/passwdutil/nss_attr.c b/usr/src/lib/passwdutil/nss_attr.c new file mode 100644 index 0000000000..daa24c73d9 --- /dev/null +++ b/usr/src/lib/passwdutil/nss_attr.c @@ -0,0 +1,320 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <errno.h> +#include <stdlib.h> +#include <pwd.h> +#include <shadow.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <nss_dbdefs.h> + +#include "passwdutil.h" + +/* from files_attr.c */ +struct passwd *private_getpwnam_r(const char *name, struct passwd *result, + char *buffer, int buflen); + +int nss_getattr(char *name, attrlist *item, pwu_repository_t *rep); +int nss_getpwnam(char *name, attrlist *items, pwu_repository_t *rep, + void **buf); + +/* + * nss function pointer table, used by passwdutil_init to initialize + * the global Repository-OPerations table "rops" + */ +struct repops nss_repops = { + NULL, /* checkhistory */ + nss_getattr, + nss_getpwnam, + NULL, /* update */ + NULL, /* putpwnam */ + NULL, /* user_to_authenticate */ + NULL, /* lock */ + NULL /* unlock */ +}; + +/* + * this structure defines the buffer used to keep state between + * get/update/put calls + */ +struct pwbuf { + struct passwd *pwd; + char *pwd_scratch; + struct spwd *spwd; + char *spwd_scratch; + char *rep_name; +}; + +/* + * We should use sysconf, but there is no sysconf name for SHADOW + * so we use these from nss_dbdefs + */ +#define PWD_SCRATCH_SIZE NSS_LINELEN_PASSWD +#define SPW_SCRATCH_SIZE NSS_LINELEN_SHADOW + + +/* + * nss_getpwnam(name, items, rep, buf) + * + */ +/*ARGSUSED*/ +int +nss_getpwnam(char *name, attrlist *items, pwu_repository_t *rep, void **buf) +{ + attrlist *p; + struct pwbuf *pwbuf; + int repositories = REP_ERANGE; /* changed if ATTR_REP_NAME is set */ + int err = PWU_SUCCESS; + + *buf = calloc(1, sizeof (struct pwbuf)); + pwbuf = (struct pwbuf *)*buf; + + /* + * determine which password structure (/etc/passwd or /etc/shadow) + * we need for the items we need to update + */ + for (p = items; p != NULL; p = p->next) { + switch (p->type) { + case ATTR_NAME: + case ATTR_UID: + case ATTR_GID: + case ATTR_AGE: + case ATTR_COMMENT: + case ATTR_GECOS: + case ATTR_HOMEDIR: + case ATTR_SHELL: + if (pwbuf->pwd == NULL) + pwbuf->pwd = (struct passwd *) + malloc(sizeof (struct passwd)); + if (pwbuf->pwd == NULL) { + errno = ENOMEM; + if (pwbuf->spwd) + free(pwbuf->spwd); + return (PWU_NOMEM); + } + break; + case ATTR_PASSWD: + case ATTR_PASSWD_SERVER_POLICY: + case ATTR_LSTCHG: + case ATTR_MIN: + case ATTR_MAX: + case ATTR_WARN: + case ATTR_INACT: + case ATTR_EXPIRE: + case ATTR_FLAG: + case ATTR_LOCK_ACCOUNT: + case ATTR_EXPIRE_PASSWORD: + case ATTR_FAILED_LOGINS: + if (pwbuf->spwd == NULL) + pwbuf->spwd = (struct spwd *) + malloc(sizeof (struct spwd)); + if (pwbuf->spwd == NULL) { + errno = ENOMEM; + if (pwbuf->pwd) + free(pwbuf->pwd); + return (PWU_NOMEM); + } + break; + case ATTR_REP_NAME: + /* get the compat names (REP_COMPAT_*) */ + repositories = get_ns(rep, PWU_READ); + break; + default: + /* + * Some other repository might have different values + * so we ignore those. + */ + break; + } + } + + if (pwbuf->pwd) { + if ((pwbuf->pwd_scratch = malloc(PWD_SCRATCH_SIZE)) == NULL) { + err = PWU_NOMEM; + goto error; + } + if (getpwnam_r(name, pwbuf->pwd, pwbuf->pwd_scratch, + PWD_SCRATCH_SIZE) == NULL) { + err = PWU_NOT_FOUND; + goto error; + } + } + + if (pwbuf->spwd) { + if ((pwbuf->spwd_scratch = malloc(SPW_SCRATCH_SIZE)) == NULL) { + err = PWU_NOMEM; + goto error; + } + if (getspnam_r(name, pwbuf->spwd, pwbuf->spwd_scratch, + SPW_SCRATCH_SIZE) == NULL) { + err = PWU_NOT_FOUND; + goto error; + } + } + + /* pwbuf->rep_name tells us where the user in fact comes from */ + if (repositories != REP_ERANGE) { + struct passwd pwd; + char pwd_scratch[PWD_SCRATCH_SIZE]; + + /* can we find the user locally? */ + if (private_getpwnam_r(name, &pwd, pwd_scratch, + PWD_SCRATCH_SIZE) != NULL) + pwbuf->rep_name = "files"; + else if (repositories & REP_COMPAT_NISPLUS) + pwbuf->rep_name = "nisplus"; + else if (repositories & REP_COMPAT_LDAP) + pwbuf->rep_name = "ldap"; + else if (repositories & REP_COMPAT_NIS) + pwbuf->rep_name = "nis"; + else + pwbuf->rep_name = "nss"; + } else + pwbuf->rep_name = "nss"; + + return (PWU_SUCCESS); +error: + if (pwbuf->pwd) free(pwbuf->pwd); + if (pwbuf->pwd_scratch) free(pwbuf->pwd_scratch); + if (pwbuf->spwd) free(pwbuf->spwd); + if (pwbuf->spwd_scratch) free(pwbuf->spwd_scratch); + free(pwbuf); + *buf = NULL; + + return (err); +} + + +/* + * nss_getattr(name, items, rep) + * + * Get attributes specified in list 'items' + */ +int +nss_getattr(char *name, attrlist *items, pwu_repository_t *rep) +{ + struct pwbuf *pwbuf; + struct passwd *pw; + struct spwd *spw; + attrlist *w; + int res = 0; + + res = nss_getpwnam(name, items, rep, (void **)&pwbuf); + if (res != PWU_SUCCESS) + return (res); + + pw = pwbuf->pwd; + spw = pwbuf->spwd; + + for (w = items; res == PWU_SUCCESS && w != NULL; w = w->next) { + switch (w->type) { + case ATTR_NAME: + if ((w->data.val_s = strdup(pw->pw_name)) == NULL) + res = PWU_NOMEM; + break; + case ATTR_COMMENT: + if ((w->data.val_s = strdup(pw->pw_comment)) == NULL) + res = PWU_NOMEM; + break; + case ATTR_GECOS: + if ((w->data.val_s = strdup(pw->pw_gecos)) == NULL) + res = PWU_NOMEM; + break; + case ATTR_HOMEDIR: + if ((w->data.val_s = strdup(pw->pw_dir)) == NULL) + res = PWU_NOMEM; + break; + case ATTR_SHELL: + if ((w->data.val_s = strdup(pw->pw_shell)) == NULL) + res = PWU_NOMEM; + break; + /* + * Nothing special needs to be done for + * server policy + */ + case ATTR_PASSWD: + case ATTR_PASSWD_SERVER_POLICY: + if ((w->data.val_s = strdup(spw->sp_pwdp)) == NULL) + res = PWU_NOMEM; + break; + case ATTR_AGE: + if ((w->data.val_s = strdup(pw->pw_age)) == NULL) + res = PWU_NOMEM; + break; + case ATTR_REP_NAME: + if ((w->data.val_s = strdup(pwbuf->rep_name)) == NULL) + res = PWU_NOMEM; + break; + + /* integer values */ + case ATTR_UID: + w->data.val_i = pw->pw_uid; + break; + case ATTR_GID: + w->data.val_i = pw->pw_gid; + break; + case ATTR_LSTCHG: + w->data.val_i = spw->sp_lstchg; + break; + case ATTR_MIN: + w->data.val_i = spw->sp_min; + break; + case ATTR_MAX: + w->data.val_i = spw->sp_max; + break; + case ATTR_WARN: + w->data.val_i = spw->sp_warn; + break; + case ATTR_INACT: + w->data.val_i = spw->sp_inact; + break; + case ATTR_EXPIRE: + w->data.val_i = spw->sp_expire; + break; + case ATTR_FLAG: + w->data.val_i = spw->sp_flag; + break; + case ATTR_FAILED_LOGINS: + w->data.val_i = spw->sp_flag & FAILCOUNT_MASK; + break; + default: + break; + } + } + + if (pwbuf->pwd) free(pwbuf->pwd); + if (pwbuf->pwd_scratch) free(pwbuf->pwd_scratch); + if (pwbuf->spwd) free(pwbuf->spwd); + if (pwbuf->spwd_scratch) free(pwbuf->spwd_scratch); + free(pwbuf); + + return (res); +} |