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_update_authtok_nis.c /main/5 1996/05/09 04:36:14 drk $ */
25 * Copyright (c) 1992-1996, by Sun Microsystems, Inc.
26 * All rights reserved.
29 #ident "@(#)unix_update_authtok_nis.c 1.43 96/02/02 SMI"
31 #include "unix_headers.h"
35 static void reencrypt_secret(pam_handle_t *, char *, char *, char *,
37 static int update_nisattr(pam_handle_t *, char *, char **,
38 struct passwd *, int, int);
44 char *data[], /* encrypted new passwd */
45 /* or new attribute info */
46 char *old, /* old passwd: clear */
47 char *new, /* new passwd: clear */
48 struct passwd *nis_pwd, /* password structure */
50 int nowarn) /* no compat mode: npd and yp server */
51 /* take the same protocol */
58 struct timeval timeout;
61 int retcode = PAM_SYSTEM_ERR;
62 char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
63 struct yppasswd yppasswd;
66 yppasswd.oldpass = NULL;
68 if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
70 (retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
74 if (strcmp(field, "passwd") == 0) {
76 * ck_passwd() already checked the old passwd. It won't get here
77 * if the old passwd is not matched.
78 * We are just preparing the passwd update packet here.
81 if ((yppasswd.oldpass = strdup(old)) == NULL) {
82 retcode = PAM_BUF_ERR;
86 if (nis_pwd->pw_passwd) {
87 memset(nis_pwd->pw_passwd, 0,
88 strlen(nis_pwd->pw_passwd));
89 free(nis_pwd->pw_passwd);
91 nis_pwd->pw_passwd = *data; /* encrypted new passwd */
94 * prompt for passwd: required for the options
95 * nis_pwd struct will be modified by update_nisattr().
96 * The encrypted passwd remains the same because we are not
97 * changing passwd here.
100 retcode = __pam_get_authtok(pamh, PAM_PROMPT, 0, PASSWORD_LEN,
101 PAM_MSG(pamh, 62, "Enter login(NIS) password: "),
102 &(yppasswd.oldpass));
103 if (retcode != PAM_SUCCESS)
106 if ((retcode = update_nisattr(pamh, field, data,
107 nis_pwd, privileged, nowarn)) != PAM_SUCCESS) {
110 /* finger, shell, or gecos info unchanged */
111 retcode = PAM_SUCCESS;
117 yppasswd.newpw = *nis_pwd;
118 if (yp_get_default_domain(&domain) != 0) {
119 syslog(LOG_ERR, "%s%s: can't get domain",
121 retcode = PAM_SYSTEM_ERR;
125 if (yp_master(domain, "passwd.byname", &master) != 0) {
126 syslog(LOG_ERR, "%s%s: can't get master for passwd map",
128 retcode = PAM_SYSTEM_ERR;
131 client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
132 if (client == NULL) {
134 "%s%s: couldn't create client to YP master",
136 retcode = PAM_SYSTEM_ERR;
141 timeout.tv_sec = 55; /* npd uses 55 seconds */
143 ans = CLNT_CALL(client, YPPASSWDPROC_UPDATE, xdr_yppasswd,
144 (char *)&yppasswd, xdr_int, (char *)&ok, timeout);
145 (void) clnt_destroy(client);
146 if (ans != RPC_SUCCESS) {
147 sprintf(messages[0], PAM_MSG(pamh, 100,
148 "%s%s: couldn't change passwd/attributes"),
150 (void) __pam_display_msg(pamh, PAM_ERROR_MSG,
153 retcode = PAM_PERM_DENIED;
158 sprintf(messages[0], PAM_MSG(pamh, 101,
159 "%s%s: Couldn't change passwd/attributes for %s"),
160 prognamep, NIS_MSG, usrname);
161 (void) __pam_display_msg(pamh, PAM_ERROR_MSG,
164 retcode = PAM_PERM_DENIED;
168 sprintf(messages[0], PAM_MSG(pamh, 102,
169 "NIS(YP) passwd/attributes changed on %s"),
171 (void) __pam_display_msg(pamh, PAM_TEXT_INFO,
174 reencrypt_secret(pamh, domain, old, new, nowarn);
176 retcode = PAM_SUCCESS;
178 if (yppasswd.oldpass) {
179 memset(yppasswd.oldpass, 0, strlen(yppasswd.oldpass));
180 free(yppasswd.oldpass);
187 update_nisattr(pam_handle_t *pamh, char *field, char **data,
188 struct passwd *nis_pwd, int privileged, int nowarn)
192 char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
194 if (nis_pwd == NULL) {
196 pam_get_item(pamh, PAM_USER, (void **)&username);
197 sprintf(messages[0], PAM_MSG(pamh, 103,
198 "System error: no NIS passwd record for %s"),
200 (void) __pam_display_msg(pamh,
201 PAM_ERROR_MSG, 1, messages, NULL);
203 return (PAM_USER_UNKNOWN);
206 if (strcmp(field, "attr") == 0) {
208 while (*data != NULL) {
209 /* AUTHTOK_DEL: not applicable */
211 if ((value = attr_match("AUTHTOK_SHELL", *data))
213 if (strcmp(value, "1") != 0) {
217 "%s: System error%s: shell is set illegally"),
219 (void) __pam_display_msg(pamh,
223 return (PAM_SYSTEM_ERR);
226 getloginshell(pamh, nis_pwd->pw_shell,
228 /* if NULL, shell unchanged */
229 if (nis_pwd->pw_shell == NULL)
235 if ((value = attr_match("AUTHTOK_HOMEDIR", *data))
238 if (strcmp(value, "1") != 0) {
242 "System error%s: homedir is set illegally."),
244 (void) __pam_display_msg(
249 return (PAM_SYSTEM_ERR);
252 gethomedir(pamh, nis_pwd->pw_dir, nowarn);
253 /* if NULL, homedir unchanged */
254 if (nis_pwd->pw_dir == NULL)
260 if ((value = attr_match("AUTHTOK_GECOS", *data))
262 /* finger information */
263 if (strcmp(value, "1") != 0) {
267 "System error: gecos is set illegally."));
268 (void) __pam_display_msg(
273 return (PAM_SYSTEM_ERR);
276 getfingerinfo(pamh, nis_pwd->pw_gecos,
278 /* if NULL, gecos unchanged */
279 if (nis_pwd->pw_gecos == NULL)
285 return (PAM_SUCCESS);
287 return (PAM_AUTHTOK_ERR);
292 * If the user has a secret key, reencrypt it.
293 * Otherwise, be quiet.
296 reencrypt_secret(pam_handle_t *pamh, char *domain, char *oldpass,
297 char *newpass, int nowarn)
299 #ifdef PAM_SECURE_RPC
300 char who[MAXNETNAMELEN+1];
301 char secret[HEXKEYBYTES+1];
302 char public[HEXKEYBYTES+1];
303 char crypt[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
304 char pkent[sizeof (crypt) + sizeof (public) + 1];
306 char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
309 if (!getsecretkey(who, secret, oldpass)) {
311 * Quiet: net is not running secure RPC
315 if (secret[0] == 0) {
317 * Quiet: user has no secret key
321 if (getpublickey(who, public) == FALSE) {
324 (void) memcpy(crypt, secret, HEXKEYBYTES);
325 (void) memcpy(crypt + HEXKEYBYTES, secret, KEYCHECKSUMSIZE);
326 crypt[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0;
327 (void) xencrypt(crypt, newpass);
328 (void) sprintf(pkent, "%s:%s", public, crypt);
329 if (yp_update(domain, PKMAP, YPOP_STORE,
330 who, strlen(who), pkent, strlen(pkent)) != 0) {
334 if (yp_master(domain, PKMAP, &master) != 0) {
335 master = "yp master"; /* should never happen */
338 sprintf(messages[0], PAM_MSG(pamh, 107,
339 "%s: secret key reencrypted for %s on %s"),
340 NIS_MSG, who, master);
341 __pam_display_msg(pamh, PAM_TEXT_INFO, 1, messages, NULL);
344 #endif /* PAM_SECURE_RPC */