1 /* $XConsortium: dce_authenticate.c /main/5 1996/05/09 04:26:26 drk $ */
3 * Copyright (c) 1995, by Sun Microsystems, Inc.
7 #ident "@(#)dce_authenticate.c 1.34 96/02/14 SMI"
10 #include <dce/sec_login.h>
11 #include <dce/dce_error.h>
12 #include <security/pam_appl.h>
13 #include <security/pam_modules.h>
17 #include <sys/types.h>
18 #include <rpc/des_crypt.h>
27 #include "xfn_mapping.h"
28 #endif /* XFN_MAPPING */
32 /* maxmimum DCE_PASSWD_LENGTH. We need to pick something for
33 * __pam_get_authtok to use.
36 #define DCE_PASSWD_LENGTH 256
41 dce_module_data_t *dsd,
55 * pam_sm_authenticate - Authenticate user
66 int err, result = PAM_AUTH_ERR;
67 char messages[1][PAM_MAX_MSG_SIZE];
74 int try_first_pass = 0;
75 int use_first_pass = 0;
80 int try_mapped_pass = 0;
81 int use_mapped_pass = 0;
84 char *firstpass = NULL, *password = NULL;
86 dce_module_data_t *dsd = NULL;
88 for (i = 0; i < argc; i++) {
89 if (strcmp(argv[i], "debug") == 0)
91 else if (strcmp(argv[i], "try_first_pass") == 0) {
96 } else if (strcmp(argv[i], "use_first_pass") == 0) {
102 } else if (strcmp(argv[i], "try_mapped_pass") == 0) {
107 } else if (strcmp(argv[i], "use_mapped_pass") == 0) {
113 } else if (strcmp(argv[i], "nowarn") == 0) {
116 syslog(LOG_ERR, "illegal module option %s", argv[i]);
120 if (flags & PAM_SILENT) warn = 0;
123 syslog(LOG_DEBUG, "DCE pam_sm_authenticate");
125 err = pam_get_user(pamh, &user, NULL);
127 if (err != PAM_SUCCESS)
130 if (user == NULL || !user[0])
131 return (PAM_AUTH_ERR);
133 /* Don't bother to authenticate root in DCE */
135 if (strcmp(user, "root") == 0)
138 /* make sure a password entry exists for this user */
139 /* we also need the uid for XFN */
141 if (!get_pw_uid(user, &pw_uid)) {
145 if (pam_get_data(pamh, DCE_DATA, (void**)&dsd) != PAM_SUCCESS ||
148 dsd = calloc(1, sizeof (dce_module_data_t));
150 result = PAM_BUF_ERR;
154 if ((err = pam_set_data(pamh, DCE_DATA, dsd, &dce_cleanup))
162 if (dsd->login_context != sec_login_default_handle) {
164 sec_login_purge_context(&dsd->login_context, &st);
168 dsd->login_context = sec_login_default_handle;
169 dsd->auth_status = PAM_AUTH_ERR;
172 dsd->reset_passwd = 0;
173 dsd->passwd_expired = 0;
174 dsd->auth_src = sec_login_auth_src_network;
176 /* see if a legitimate DCE user */
178 if (!sec_login_setup_identity((unsigned char *)user,
179 sec_login_no_flags, &dsd->login_context, &st)) {
181 dce_error_string_t text;
183 "PAM: DCE sec_login_setup_identity: %s",
184 get_dce_error_message(st, text));
186 if (st == sec_rgy_object_not_found) {
187 /* mask the unknown user case */
190 result = PAM_AUTH_ERR;
195 err = pam_get_item(pamh, PAM_AUTHTOK, (void **) &firstpass);
197 if (err != PAM_SUCCESS && (use_first_pass || use_mapped_pass)) {
198 result = PAM_AUTH_ERR;
200 syslog(LOG_DEBUG, "PAM: DCE goto out!");
204 if (firstpass != NULL && (ignore || invalid_user))
209 if (firstpass == NULL) {
210 if (use_mapped_pass) goto out;
211 } else if (try_mapped_pass || use_mapped_pass) {
212 char dcepass[MAP_PASSLEN+1];
216 saved_uid = geteuid();
218 if (saved_uid != pw_uid && getuid() == 0 &&
219 seteuid(pw_uid) < 0) {
221 "xfn_get_mapped_passwd: seteuid: %m");
222 /* continue since we might be able to get mapping */
225 got_mapped_pass = xfn_get_mapped_password(
226 debug ? XFN_MAP_DEBUG : 0, user, DCE_XFN_PASS_ATTR,
227 firstpass, dcepass, sizeof (dcepass));
229 if (geteuid() != saved_uid && seteuid(saved_uid) < 0) {
231 "xfn_get_mapped_passwd seteuid restore: %m");
232 /* XXX: what should we do here? */
235 if (got_mapped_pass) {
238 attempt_dce_login(pamh, dsd, &st, user, dcepass);
240 memset(dcepass, 0, MAP_PASSLEN);
242 if (result == PAM_SUCCESS ||
243 st == sec_login_s_acct_invalid) goto out;
245 if (use_mapped_pass) goto out;
249 if (firstpass == NULL) {
250 if (use_first_pass) goto out;
251 } else if (use_first_pass || try_first_pass) {
253 result = attempt_dce_login(pamh, dsd, &st,
256 if (result == PAM_SUCCESS ||
257 st == sec_login_s_acct_invalid ||
264 * Get the password from the user
268 syslog(LOG_DEBUG, "DCE pam_sm_auth prompting for password");
270 if (firstpass == NULL &&
271 !(try_first_pass||try_mapped_pass||invalid_user))
272 (void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 10,
275 (void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 11,
280 err = __pam_get_authtok(pamh, PAM_PROMPT, PAM_AUTHTOK,
281 DCE_PASSWD_LENGTH,messages[0], &password);
283 syslog(LOG_DEBUG, "DCE __pam_get_authtok = %d", err);
285 if (err != PAM_SUCCESS) {
290 if (password == NULL) {
291 /* Need a password to proceed */
292 result = PAM_AUTH_ERR;
296 if (firstpass == NULL) {
297 /* this is the first password, stash it away */
298 pam_set_item(pamh, PAM_AUTHTOK, password);
301 /* one last ditch attempt to login to DCE */
303 if (invalid_user || ignore)
306 result = attempt_dce_login(pamh, dsd, &st, user, password);
309 /* we had to prompt for DCE password, so attempt to */
310 /* update mapping iff we got a good DCE password */
312 if (try_mapped_pass && result == PAM_SUCCESS && firstpass) {
315 saved_uid = geteuid();
317 if (saved_uid != pw_uid && seteuid(pw_uid) < 0) {
318 syslog(LOG_ERR, "xfn_get_mapped_passwd: seteuid: %m");
322 xfn_update_mapped_password(debug ? XFN_MAP_DEBUG : 0,
323 user, DCE_XFN_PASS_ATTR, firstpass, password);
325 if (geteuid() != saved_uid && seteuid(saved_uid) < 0) {
327 "xfn_get_mapped_passwd seteuid restore: %m");
328 /* XXX: what should we do here? */
339 if (password != NULL)
340 memset(password, 0, strlen(password));
343 result = PAM_USER_UNKNOWN;
346 dsd->auth_status = result;
354 dce_module_data_t *dsd,
359 sec_passwd_rec_t passwd_rec;
360 boolean32 login_valid = 0;
361 error_status_t set_st;
363 /* have to strdup password because the call clears it */
364 passwd_rec.key.tagged_union.plain = (idl_char *) strdup(dce_pass);
365 if (passwd_rec.key.tagged_union.plain == NULL) {
366 return (PAM_BUF_ERR);
368 passwd_rec.key.key_type = sec_passwd_plain;
369 passwd_rec.pepper = NULL;
370 passwd_rec.version_number = sec_passwd_c_version_none;
372 login_valid = sec_login_valid_and_cert_ident(dsd->login_context,
373 &passwd_rec, &dsd->reset_passwd, &dsd->auth_src, st);
376 dce_error_string_t text;
378 syslog(LOG_DEBUG, "sec_login_valid_and_cert_ident: %s",
379 get_dce_error_message(*st, text));
382 if (*st == sec_login_s_acct_invalid && dsd->warn) {
383 char messages[1][PAM_MAX_MSG_SIZE];
386 PAM_MSG(pamh, 12, "Error: Your DCE Account has expired.\n"));
387 __pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL);
390 /* the call to sec_login_valid_and_cert_ident already zeros */
391 /* out the password, so we just free it */
393 free(passwd_rec.key.tagged_union.plain);
395 return (login_valid ? PAM_SUCCESS : PAM_AUTH_ERR);
405 dce_module_data_t *dsd = (dce_module_data_t *) data;
409 syslog(LOG_DEBUG, "DCE dce_cleanup pam_sm_auth_status(%d)",
413 if (!dsd->login_context != sec_login_default_handle) {
418 /* if pam_end as PAM_SUCCESS, clean up based on value in */
419 /* auth_status, otherwise just purge the context */
421 if (pam_status == PAM_SUCCESS) {
422 pam_sec_login_free_context(dsd->auth_status,
423 &dsd->login_context, &st);
425 sec_login_purge_context(&dsd->login_context, &st);
427 dce_error_string_t text;
428 syslog(LOG_DEBUG, "sec_login_purge_context: %s",
429 get_dce_error_message(st, text));