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: dce_password.c /main/5 1996/05/09 04:26:43 drk $ */
25 * Copyright (c) 1995, by Sun Microsystems, Inc.
26 * All rights reserved.
29 #ident "@(#)dce_password.c 1.22 96/02/14 SMI"
31 #include <security/pam_appl.h>
32 #include <security/pam_modules.h>
37 #include <sys/types.h>
42 #include <dce/binding.h>
43 #include <dce/sec_login.h>
44 #include <dce/dce_error.h>
51 #include "xfn_mapping.h"
66 * XXX: This module is NOT finished!
77 int err, result = PAM_AUTH_ERR;
78 char *newpass = NULL, *vnewpass = NULL;
80 int try_first_pass = 0;
81 int use_first_pass = 0;
82 char *firstpass = NULL;
85 int try_mapped_pass = 0;
86 int use_mapped_pass = 0;
92 dce_module_data_t *dsd = NULL;
93 error_status_t status;
96 syslog(LOG_DEBUG, "DCE Authentication\n");
98 for (i = 0; i < argc; i++) {
99 if (strcmp(argv[i], "debug") == 0)
101 else if (strcmp(argv[i], "try_first_pass") == 0)
103 else if (strcmp(argv[i], "use_first_pass") == 0)
106 else if (strcmp(argv[i], "try_mapped_pass") == 0)
108 else if (strcmp(argv[i], "use_mapped_pass") == 0)
112 syslog(LOG_DEBUG, "illegal scheme option %s", argv[i]);
116 if (flags & PAM_PRELIM_CHECK) {
118 /* try and bind to registry master of local cell */
120 sec_rgy_handle_t rh = sec_rgy_default_handle;
122 sec_rgy_site_open_update(NULL, &rh, &status);
123 if (status == error_status_ok) {
124 sec_rgy_site_close(rh, &status);
125 return (PAM_SUCCESS);
127 return (PAM_AUTHTOK_ERR);
130 /* make sure PAM framework is telling us to update passwords */
131 if (!(flags & PAM_UPDATE_AUTHTOK)) {
132 syslog(LOG_ERR, "dce pam_sm_chauthtok: bad flags: %d", flags);
133 return (PAM_SYSTEM_ERR);
137 if (flags & PAM_CHANGE_EXPIRED_AUTHTOK) {
138 if (pam_get_data(pamh, DCE_DATA, (void **)&dsd)
140 if (!dsd->passwd_expired)
145 if ((err = pam_get_item(pamh, PAM_USER, (void **) &user)) < 0)
148 /* Don't bother to handle root in DCE */
150 if (strcmp(user, "root") == 0)
154 if (use_mapped_pass || try_mapped_pass) {
155 int got_mapped = 0, updated_mapped = 0;
156 char dcepass[MAP_PASSLEN+1];
158 if ((err = pam_get_item(pamh, PAM_AUTHTOK,
159 (void **) &newpass)) < 0)
161 if ((err = pam_get_item(pamh, PAM_OLDAUTHTOK,
162 (void **) &oldpass)) < 0)
165 if (!get_pw_uid(user, &pw_uid)) {
166 return (PAM_AUTHTOK_ERR);
169 /* XXX: need to seteuid */
171 saved_uid = geteuid();
173 if (saved_uid != pw_uid && getuid() == 0 &&
174 seteuid(pw_uid) < 0) {
176 "xfn_get_mapped_passwd: seteuid: %m");
177 return (PAM_AUTHTOK_ERR);
180 got_mapped = xfn_get_mapped_password(0, user,
181 DCE_XFN_PASS_ATTR, oldpass, dcepass, sizeof (dcepass));
185 updated_mapped = xfn_update_mapped_password(
186 0, user, DCE_XFN_PASS_ATTR, newpass,
189 memset(dcepass, 0, sizeof (dcepass));
192 /* probably should prompt for DCE password */
193 /* and attempt to update it */
196 if (geteuid() != saved_uid && seteuid(saved_uid) < 0) {
198 "xfn_get_mapped_passwd seteuid restore: %m");
199 /* XXX: what should we do here? */
202 if (use_mapped_pass) {
204 return (PAM_SUCCESS);
206 return (PAM_AUTHTOK_ERR);
209 return (PAM_AUTHTOK_ERR);
211 #endif /* XFN_MAPPING */
213 if (try_first_pass || use_first_pass) {
215 if ((err = pam_get_item(pamh, PAM_AUTHTOK,
216 (void **) &newpass)) < 0)
218 if ((err = pam_get_item(pamh, PAM_OLDAUTHTOK,
219 (void **) &oldpass)) < 0)
222 result = dce_changepw(user, oldpass, newpass);
224 if (result == PAM_SUCCESS) {
225 /* might need to update PAM_OLDAUTHTOK and PAM_NEWAUTHTOK */
229 /* assume we need to prompt for old DCE password? */
231 oldpass = get_passwd(pamh, PAM_MSG(pamh, 20,
232 "Old DCE password: "));
234 if (oldpass == NULL || oldpass[0] == '\0') {
235 /* Need a password to proceed */
236 result = PAM_AUTHTOK_ERR;
240 result = dce_changepw(user, oldpass, newpass);
242 if (result == PAM_SUCCESS) {
243 /* might need to update PAM_OLDAUTHTOK and PAM_NEWAUTHTOK */
249 /* prompt for both old and new passwords */
251 if (firstpass == NULL && !(try_first_pass||try_mapped_pass))
252 oldpass = get_passwd(pamh, PAM_MSG(pamh, 20,
253 "Old DCE password: "));
255 oldpass = get_passwd(pamh, PAM_MSG(pamh, 20,
256 "Old DCE password: "));
258 if (oldpass == NULL || oldpass[0] == '\0') {
259 /* Need a password to proceed */
260 result = PAM_AUTHTOK_ERR;
264 if (firstpass == NULL && !(try_first_pass||try_mapped_pass))
265 newpass = get_passwd(pamh, PAM_MSG(pamh, 21,
266 "New DCE password: "));
268 newpass = get_passwd(pamh, PAM_MSG(pamh, 21,
269 "New DCE password: "));
271 if (newpass == NULL || newpass[0] == '\0') {
272 /* Need a password to proceed */
273 result = PAM_AUTHTOK_ERR;
277 if (firstpass == NULL && !(try_first_pass||try_mapped_pass))
278 vnewpass = get_passwd(pamh,
280 "Re-enter new DCE password: "));
282 vnewpass = get_passwd(pamh,
284 "Re-enter new DCE password: "));
286 if (vnewpass == NULL || vnewpass[0] == '\0') {
287 /* Need a password to proceed */
288 result = PAM_AUTHTOK_ERR;
292 if (strcmp(newpass, vnewpass)) {
293 result = PAM_AUTHTOK_ERR;
297 result = dce_changepw(user, oldpass, newpass);
299 if (result == PAM_SUCCESS) {
300 /* might need to update PAM_OLDAUTHTOK and PAM_NEWAUTHTOK) */
305 memset(oldpass, 0, strlen(oldpass));
310 memset(newpass, 0, strlen(newpass));
316 memset(vnewpass, 0, strlen(vnewpass));
329 error_status_t status;
330 sec_rgy_handle_t rgy_handle = sec_rgy_default_handle;
331 sec_rgy_login_name_t name_key;
332 sec_rgy_cursor_t account_cursor;
333 sec_rgy_login_name_t name_result;
334 sec_rgy_sid_t id_sid;
335 sec_rgy_unix_sid_t unix_sid;
336 sec_rgy_acct_key_t key_parts;
337 sec_rgy_acct_user_t user_part;
338 sec_rgy_acct_admin_t admin_part;
339 sec_passwd_rec_t new_key, caller_key;
340 sec_passwd_version_t new_key_version;
341 sec_login_handle_t login_context = sec_login_default_handle;
342 sec_passwd_rec_t passwd_rec;
343 boolean32 reset_pass = 0, login_valid = 0;
344 sec_login_auth_src_t auth_src;
346 static char *krb5 = "KRB5CCNAME";
347 char *krb5_value = NULL;
349 /* stash away the value of KRB5CCNAME, if there is one set */
352 krb5_value = malloc(strlen(krb5)+1+strlen(env)+1);
354 sprintf(krb5_value, "%s=%s", krb5, env);
356 status = sec_login_s_no_current_context;
361 /* first we a get a login context. A future version should */
362 /* check and see if there is a current context with the */
363 /* same name as the user we are setting */
365 if (!sec_login_setup_identity((unsigned_char_p_t) account_name,
366 sec_login_no_flags, &login_context, &status)) {
370 /* have to strdup password because the call clears it */
371 passwd_rec.key.tagged_union.plain =
372 (idl_char *) strdup(old_pass);
373 if (passwd_rec.key.tagged_union.plain == NULL) {
374 status = sec_login_s_no_current_context;
378 passwd_rec.key.key_type = sec_passwd_plain;
379 passwd_rec.pepper = NULL;
380 passwd_rec.version_number = sec_passwd_c_version_none;
382 login_valid = sec_login_validate_identity(login_context,
383 &passwd_rec, &reset_pass, &auth_src, &status);
385 free(passwd_rec.key.tagged_union.plain); /* already memset */
390 sec_login_set_context(login_context, &status);
392 if (status != error_status_ok)
395 /* we now have a context with the same account as the one */
396 /* we are trying to change the password on. Lets talk to the */
399 sec_rgy_site_open(NULL, &rgy_handle, &status);
401 if (status != error_status_ok) {
405 caller_key.key.key_type = sec_passwd_plain;
406 caller_key.pepper = NULL;
407 caller_key.version_number = sec_passwd_c_version_none;
408 caller_key.key.tagged_union.plain = (idl_char *) old_pass;
410 sec_rgy_cursor_reset(&account_cursor);
412 strcpy((char *)name_key.pname, account_name);
413 name_key.gname[0] = '\0';
414 name_key.oname[0] = '\0';
416 /* need to do this in order to get the org and group for the */
417 /* account. All we want is name_result... */
431 if (status != error_status_ok)
434 caller_key.key.key_type = sec_passwd_plain;
435 caller_key.pepper = NULL;
436 caller_key.version_number = sec_passwd_c_version_none;
437 caller_key.key.tagged_union.plain = (idl_char *) old_pass;
439 new_key.key.key_type = sec_passwd_plain;
440 new_key.pepper = NULL;
441 new_key.version_number = sec_passwd_c_version_none;
442 new_key.key.tagged_union.plain = (idl_char *) new_pass;
444 /* rock and roll. lets try to update the password... */
456 /* restore the old KRB5CCNAME value */
461 if (rgy_handle != sec_rgy_default_handle) {
462 error_status_t st; /* don't trash status */
464 sec_rgy_site_close(rgy_handle, &st);
467 if (login_context != sec_login_default_handle) {
468 error_status_t st; /* don't trash status */
470 sec_login_purge_context(&login_context, &st);
473 if (status == error_status_ok) {
474 return (PAM_SUCCESS);
476 return (PAM_AUTHTOK_ERR);
490 err = __pam_get_authtok(pamh, PAM_PROMPT, 0, 256, prompt, &p);
492 if (err != PAM_SUCCESS) {