2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: unix_get_authtokattr.c /main/8 1996/11/21 20:00:50 drk $ */
25 * Copyright (c) 1992-1995, by Sun Microsystems, Inc.
26 * All rights reserved.
29 #ident "@(#)unix_get_authtokattr.c 1.59 96/01/07 SMI"
31 #include "unix_headers.h"
33 #define XOS_USE_NO_LOCKING
34 #define X_INCLUDE_TIME_H
35 #include <X11/Xos_r.h>
38 static void _np_nss_initf_shadow(nss_db_params_t *);
39 static void _np_setspent();
40 static void _np_endspent();
41 static struct spwd * _np_getspent_r(struct spwd *, char *, int);
42 static struct spwd * _np_getspent();
46 * __get_authtoken_attr():
47 * To get authentication token attribute values.
49 * This function calls ck_perm() first to check the caller's
50 * permission. If the check succeeds, it will read the
51 * attribute/value pairs from the shadow password entry of
52 * the user specified by the authentication handle "pamh"
53 * and store them into a character array and return.
57 * XXX: We use our own version of the shadow passwd getent routine.
58 * See below for details. Compatible with version 2 of the name service
59 * switch. In the future, the name service switch implementation may
60 * change and these functions and the Makefile may have to
74 char value[PAM_MAX_ATTR_SIZE];
79 char **get_attributes;
86 char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
92 for (i = 0; i < argc; i++) {
93 if (strcmp(argv[i], "debug") == 0)
95 else if (strcmp(argv[i], "nowarn") == 0)
98 syslog(LOG_ERR, "illegal UNIX module option %s",
104 "__get_authtoken_attr(): repository=%s",
105 repository_to_string(repository));
107 if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
109 (retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
113 if ((get_attributes = (char **)
114 calloc(PAM_MAX_NUM_ATTR, sizeof (char *))) == NULL)
115 return (PAM_BUF_ERR);
117 /* repository must be specified in the command line. */
118 if (repository == PAM_REP_DEFAULT) {
119 sprintf(messages[0], PAM_MSG(pamh, 40,
120 "You must specify repository when displaying passwd attributes"));
121 (void) __pam_display_msg(pamh, PAM_ERROR_MSG,
123 return (PAM_AUTHTOK_ERR);
126 if (!IS_FILES(repository) && !IS_NIS(repository) &&
127 !IS_NISPLUS(repository)) {
128 sprintf(messages[0], PAM_MSG(pamh, 41,
129 "%s: System error: repository out of range"), prognamep);
130 (void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1,
132 return (PAM_SYSTEM_ERR);
136 if (usrname == NULL || *usrname == NULL) {
137 /* print nis+ table */
139 * Cat the table using our private _np_getspent()
141 if (!IS_NISPLUS(repository)) {
142 sprintf(messages[0], PAM_MSG(pamh, 42,
143 "Unable to retrieve username."));
144 (void) __pam_display_msg(pamh, PAM_ERROR_MSG,
146 return (PAM_AUTHTOK_RECOVERY_ERR);
149 (void) _np_setspent();
150 while ((psp = _np_getspent()) != NULL) {
152 sprintf(value, "%s ", psp->sp_namp);
154 if (psp->sp_pwdp == NULL) {
157 } else if ((int)strlen(psp->sp_pwdp) < NUMCP) {
165 if (psp->sp_max != -1) {
166 _Xgtimeparams gmtime_buf;
167 strcpy(value, messages[0]);
168 if (psp->sp_lstchg) {
169 lstchg = psp->sp_lstchg * DAY;
170 tmp = _XGmtime(&lstchg, gmtime_buf);
172 "%s %.2d/%.2d/%.2d ",
175 tmp->tm_mday, tmp->tm_year);
181 strcpy(value, messages[0]);
182 if ((psp->sp_min >= 0) && (psp->sp_warn > 0)) {
186 psp->sp_min, psp->sp_max,
188 } else if (psp->sp_min >= 0) {
191 psp->sp_min, psp->sp_max);
192 } else if (psp->sp_warn > 0) {
195 psp->sp_max, psp->sp_warn);
202 (void) __pam_display_msg(pamh, PAM_TEXT_INFO,
205 (void) _np_endspent();
208 * If password table does not have any entries or is missing,
209 * return fatal error.
214 "%s: Unexpected failure. Password database unchanged."),
216 (void) __pam_display_msg(pamh, PAM_ERROR_MSG,
218 return (PAM_SYSTEM_ERR);
220 return (PAM_SUCCESS);
222 #endif /* PAM_NISPLUS */
224 retcode = ck_perm(pamh, repository,
225 (char *)domain, &pwd, &shpwd, &privileged,
226 (void **)&passwd_res, getuid(), debug, nowarn);
233 /* get attribute "AUTHTOK_STATUS" */
234 if (shpwd->sp_pwdp == NULL)
235 (void) strcpy(value, "NP ");
236 else if ((int)strlen(shpwd->sp_pwdp) < NUMCP)
237 (void) strcpy(value, "LK ");
239 (void) strcpy(value, "PS ");
240 setup_attr(get_attributes, k++, "AUTHTOK_STATUS=", value);
243 if (shpwd->sp_max != -1) {
244 /* get attribute "AUTHTOK_LASTCHANGE" */
245 if (shpwd->sp_lstchg) {
246 lstchg = shpwd->sp_lstchg * DAY;
247 sprintf(value, "%d", lstchg);
249 sprintf(value, "%d", shpwd->sp_lstchg);
251 setup_attr(get_attributes, k++,
252 "AUTHTOK_LASTCHANGE=", value);
254 /* get attribute "AUTHTOK_MINAGE" */
255 /* "AUTHTOK_MAXAGE", and "AUTHTOK_WARNDATE" */
256 if ((shpwd->sp_min >= 0) && (shpwd->sp_warn > 0)) {
257 sprintf(value, "%d", shpwd->sp_min);
258 setup_attr(get_attributes, k++,
259 "AUTHTOK_MINAGE=", value);
260 sprintf(value, "%d", shpwd->sp_max);
261 setup_attr(get_attributes, k++,
262 "AUTHTOK_MAXAGE=", value);
263 sprintf(value, "%d", shpwd->sp_warn);
264 setup_attr(get_attributes, k++,
265 "AUTHTOK_WARNDATE=", value);
267 if (shpwd->sp_min >= 0) {
268 sprintf(value, "%d", shpwd->sp_min);
269 setup_attr(get_attributes, k++,
270 "AUTHTOK_MINAGE=", value);
271 sprintf(value, "%d", shpwd->sp_max);
272 setup_attr(get_attributes, k++,
273 "AUTHTOK_MAXAGE=", value);
275 if (shpwd->sp_warn > 0) {
276 sprintf(value, "%d", shpwd->sp_max);
277 setup_attr(get_attributes, k++,
278 "AUTHTOK_MAXAGE=", value);
279 sprintf(value, "%d", shpwd->sp_warn);
280 setup_attr(get_attributes, k++,
281 "AUTHTOK_WARNDATE=", value);
283 sprintf(value, "%d", shpwd->sp_max);
284 setup_attr(get_attributes, k++,
285 "AUTHTOK_MAXAGE=", value);
290 /* terminate with NULL */
291 setup_attr(get_attributes, k, NULL, NULL);
293 *ga_getattr = &get_attributes[0];
295 free_passwd_structs(pwd, shpwd);
296 return (PAM_SUCCESS);
304 * XXX Our private version of the switch frontend for getspent. We want to
305 * search just the nisplus sp file, so we want to bypass normal nsswitch.conf
306 * based processing. This implementation compatible with version 2 of the
307 * name service switch.
310 #define NSS_NISPLUS_ONLY "nisplus"
312 int str2spwd(const char *, int, void *, char *, int);
314 static DEFINE_NSS_DB_ROOT(db_root);
315 static DEFINE_NSS_GETENT(context);
318 _np_nss_initf_shadow(p)
321 p->name = NSS_DBNAM_SHADOW;
322 p->config_name = NSS_DBNAM_PASSWD; /* Use config for "passwd" */
323 p->default_config = NSS_NISPLUS_ONLY; /* Use nisplus only */
324 p->flags = NSS_USE_DEFAULT_CONFIG;
330 nss_setent(&db_root, _np_nss_initf_shadow, &context);
336 nss_endent(&db_root, _np_nss_initf_shadow, &context);
337 nss_delete(&db_root);
341 _np_getspent_r(result, buffer, buflen)
349 /* In getXXent_r(), protect the unsuspecting caller from +/- entries */
352 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd);
353 /* No key to fill in */
354 nss_getent(&db_root, _np_nss_initf_shadow, &context, &arg);
355 } while (arg.returnval != 0 &&
356 (nam = ((struct spwd *)arg.returnval)->sp_namp) != 0 &&
357 (*nam == '+' || *nam == '-'));
359 return (struct spwd *) NSS_XbyY_FINI(&arg);
362 static nss_XbyY_buf_t *buffer;
369 b = NSS_XbyY_ALLOC(&buffer, sizeof (struct spwd), NSS_BUFLEN_SHADOW);
371 return (b == 0 ? 0 : _np_getspent_r(b->result, b->buffer, b->buflen));
374 #endif /* PAM_NISPLUS */