2 * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 #include <sys/types.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
59 #ifndef POSIX_GETPWNAM_R
61 /* These functions translate from the old Digital UNIX 3.x interface
66 posix_getpwnam_r(const char *name
, struct passwd
*pwd
,
67 char *buffer
, int len
, struct passwd
**result
)
69 int ret
= getpwnam_r(name
, pwd
, buffer
, len
);
83 #define getpwnam_r posix_getpwnam_r
86 posix_getpwuid_r(uid_t uid
, struct passwd
*pwd
,
87 char *buffer
, int len
, struct passwd
**result
)
89 int ret
= getpwuid_r(uid
, pwd
, buffer
, len
);
103 #define getpwuid_r posix_getpwuid_r
105 #endif /* POSIX_GETPWNAM_R */
110 #define SIA_DEBUG(X) SIALOG X
114 char ticket
[MaxPathLen
];
125 siad_chk_invoker(void)
127 SIA_DEBUG(("DEBUG", "siad_chk_invoker"));
132 siad_ses_init(SIAENTITY
*entity
, int pkgind
)
134 struct state
*s
= malloc(sizeof(*s
));
135 SIA_DEBUG(("DEBUG", "siad_ses_init"));
138 memset(s
, 0, sizeof(*s
));
139 entity
->mech
[pkgind
] = (int*)s
;
144 setup_name(SIAENTITY
*e
, prompt_t
*p
)
146 SIA_DEBUG(("DEBUG", "setup_name"));
147 e
->name
= malloc(SIANAMEMIN
+1);
149 SIA_DEBUG(("DEBUG", "failed to malloc %u bytes", SIANAMEMIN
+1));
152 p
->prompt
= (unsigned char*)"login: ";
153 p
->result
= (unsigned char*)e
->name
;
154 p
->min_result_length
= 1;
155 p
->max_result_length
= SIANAMEMIN
;
156 p
->control_flags
= 0;
161 setup_password(SIAENTITY
*e
, prompt_t
*p
)
163 SIA_DEBUG(("DEBUG", "setup_password"));
164 e
->password
= malloc(SIAMXPASSWORD
+1);
165 if(e
->password
== NULL
){
166 SIA_DEBUG(("DEBUG", "failed to malloc %u bytes", SIAMXPASSWORD
+1));
169 p
->prompt
= (unsigned char*)"Password: ";
170 p
->result
= (unsigned char*)e
->password
;
171 p
->min_result_length
= 0;
172 p
->max_result_length
= SIAMXPASSWORD
;
173 p
->control_flags
= SIARESINVIS
;
179 common_auth(sia_collect_func_t
*collect
,
184 prompt_t prompts
[2], *pr
;
185 char *toname
, *toinst
;
188 SIA_DEBUG(("DEBUG", "common_auth"));
189 if((siastat
== SIADSUCCESS
) && (geteuid() == 0))
192 SIA_DEBUG(("DEBUG", "entity == NULL"));
193 return SIADFAIL
| SIADSTOP
;
197 name
= entity
->acctname
;
199 if((collect
!= NULL
) && entity
->colinput
) {
203 if(setup_name(entity
, pr
) != SIADSUCCESS
)
207 if(entity
->password
== NULL
){
208 if(setup_password(entity
, pr
) != SIADSUCCESS
)
214 if((*collect
)(240, SIAONELINER
, (unsigned char*)"", num
,
215 prompts
) != SIACOLSUCCESS
){
216 SIA_DEBUG(("DEBUG", "collect failed"));
217 return SIADFAIL
| SIADSTOP
;
220 if((*collect
)(0, SIAFORM
, (unsigned char*)"", num
,
221 prompts
) != SIACOLSUCCESS
){
222 SIA_DEBUG(("DEBUG", "collect failed"));
223 return SIADFAIL
| SIADSTOP
;
229 if(name
== NULL
|| name
[0] == '\0'){
230 SIA_DEBUG(("DEBUG", "name is null"));
234 if(entity
->password
== NULL
|| strlen(entity
->password
) > SIAMXPASSWORD
){
235 SIA_DEBUG(("DEBUG", "entity->password is null"));
240 char realm
[REALM_SZ
];
242 struct passwd pw
, *pwd
, fpw
, *fpwd
;
243 char pwbuf
[1024], fpwbuf
[1024];
244 struct state
*s
= (struct state
*)entity
->mech
[pkgind
];
246 if(getpwnam_r(name
, &pw
, pwbuf
, sizeof(pwbuf
), &pwd
) != 0){
247 SIA_DEBUG(("DEBUG", "failed to getpwnam(%s)", name
));
251 snprintf(s
->ticket
, sizeof(s
->ticket
),
252 TKT_ROOT
"%u_%u", (unsigned)pwd
->pw_uid
, (unsigned)getpid());
253 krb_get_lrealm(realm
, 1);
256 if(entity
->authtype
== SIA_A_SUAUTH
){
258 #ifdef SIAENTITY_HAS_OUID
263 if(getpwuid_r(ouid
, &fpw
, fpwbuf
, sizeof(fpwbuf
), &fpwd
) != 0){
264 SIA_DEBUG(("DEBUG", "failed to getpwuid(%u)", ouid
));
267 snprintf(s
->ticket
, sizeof(s
->ticket
), TKT_ROOT
"_%s_to_%s_%d",
268 fpwd
->pw_name
, pwd
->pw_name
, getpid());
269 if(strcmp(pwd
->pw_name
, "root") == 0){
270 toname
= fpwd
->pw_name
;
271 toinst
= pwd
->pw_name
;
274 if(entity
->authtype
== SIA_A_REAUTH
)
275 snprintf(s
->ticket
, sizeof(s
->ticket
), "%s", tkt_string());
277 krb_set_tkt_string(s
->ticket
);
279 setuid(0); /* XXX fix for fix in tf_util.c */
280 if(krb_kuserok(toname
, toinst
, realm
, name
)){
281 SIA_DEBUG(("DEBUG", "%s.%s@%s is not allowed to login as %s",
282 toname
, toinst
, realm
, name
));
285 ret
= krb_verify_user(toname
, toinst
, realm
,
286 entity
->password
, getuid() == 0, NULL
);
288 SIA_DEBUG(("DEBUG", "krb_verify_user: %s", krb_get_err_text(ret
)));
289 if(ret
!= KDC_PR_UNKNOWN
)
290 /* since this is most likely a local user (such as
291 root), just silently return failure when the
292 principal doesn't exist */
293 SIALOG("WARNING", "krb_verify_user(%s.%s): %s",
294 toname
, toinst
, krb_get_err_text(ret
));
297 if(sia_make_entity_pwd(pwd
, entity
) == SIAFAIL
)
306 siad_ses_authent(sia_collect_func_t
*collect
,
311 SIA_DEBUG(("DEBUG", "siad_ses_authent"));
312 return common_auth(collect
, entity
, siastat
, pkgind
);
316 siad_ses_estab(sia_collect_func_t
*collect
,
317 SIAENTITY
*entity
, int pkgind
)
319 SIA_DEBUG(("DEBUG", "siad_ses_estab"));
324 siad_ses_launch(sia_collect_func_t
*collect
,
328 static char env
[MaxPathLen
];
329 struct state
*s
= (struct state
*)entity
->mech
[pkgind
];
330 SIA_DEBUG(("DEBUG", "siad_ses_launch"));
332 chown(s
->ticket
, entity
->pwd
->pw_uid
, entity
->pwd
->pw_gid
);
333 snprintf(env
, sizeof(env
), "KRBTKFILE=%s", s
->ticket
);
339 if(k_afs_cell_of_file(entity
->pwd
->pw_dir
, cell
, sizeof(cell
)) == 0)
347 siad_ses_release(SIAENTITY
*entity
, int pkgind
)
349 SIA_DEBUG(("DEBUG", "siad_ses_release"));
350 if(entity
->mech
[pkgind
])
351 free(entity
->mech
[pkgind
]);
356 siad_ses_suauthent(sia_collect_func_t
*collect
,
361 SIA_DEBUG(("DEBUG", "siad_ses_suauth"));
364 if(entity
->name
== NULL
)
366 if(entity
->name
[0] == 0) {
368 entity
->name
= strdup("root");
369 if (entity
->name
== NULL
)
372 return common_auth(collect
, entity
, siastat
, pkgind
);
375 /* The following functions returns the default fail */
378 siad_ses_reauthent (sia_collect_func_t
*collect
,
384 SIA_DEBUG(("DEBUG", "siad_ses_reauthent"));
385 if(entity
== NULL
|| entity
->name
== NULL
)
387 ret
= common_auth(collect
, entity
, siastat
, pkgind
);
388 if((ret
& SIADSUCCESS
)){
389 /* launch isn't (always?) called when doing reauth, so we must
390 duplicate some code here... */
391 struct state
*s
= (struct state
*)entity
->mech
[pkgind
];
392 chown(s
->ticket
, entity
->pwd
->pw_uid
, entity
->pwd
->pw_gid
);
395 if(k_afs_cell_of_file(entity
->pwd
->pw_dir
,
396 cell
, sizeof(cell
)) == 0)
405 siad_chg_finger (sia_collect_func_t
*collect
,
406 const char *username
,
410 SIA_DEBUG(("DEBUG", "siad_chg_finger"));
415 sia_message(sia_collect_func_t
*collect
, int rendition
,
416 const char *title
, const char *message
)
419 prompt
.prompt
= (unsigned char*)message
;
420 (*collect
)(0, rendition
, (unsigned char*)title
, 1, &prompt
);
424 init_change(sia_collect_func_t
*collect
, krb_principal
*princ
)
427 char old_pw
[MAX_KPW_LEN
+1];
432 SIA_DEBUG(("DEBUG", "init_change"));
433 prompt
.prompt
= (unsigned char*)"Old password: ";
434 prompt
.result
= (unsigned char*)old_pw
;
435 prompt
.min_result_length
= 0;
436 prompt
.max_result_length
= sizeof(old_pw
) - 1;
437 prompt
.control_flags
= SIARESINVIS
;
438 asprintf(&msg
, "Changing password for %s", krb_unparse_name(princ
));
440 SIA_DEBUG(("DEBUG", "out of memory"));
443 ret
= (*collect
)(60, SIAONELINER
, (unsigned char*)msg
, 1, &prompt
);
445 SIA_DEBUG(("DEBUG", "ret = %d", ret
));
446 if(ret
!= SIACOLSUCCESS
)
448 snprintf(tktstring
, sizeof(tktstring
),
449 TKT_ROOT
"_cpw_%u", (unsigned)getpid());
450 krb_set_tkt_string(tktstring
);
452 ret
= krb_get_pw_in_tkt(princ
->name
, princ
->instance
, princ
->realm
,
453 PWSERV_NAME
, KADM_SINST
, 1, old_pw
);
454 if (ret
!= KSUCCESS
) {
455 SIA_DEBUG(("DEBUG", "krb_get_pw_in_tkt: %s", krb_get_err_text(ret
)));
456 if (ret
== INTK_BADPW
)
457 sia_message(collect
, SIAWARNING
, "", "Incorrect old password.");
459 sia_message(collect
, SIAWARNING
, "", "Kerberos error.");
460 memset(old_pw
, 0, sizeof(old_pw
));
463 if(chown(tktstring
, getuid(), -1) < 0){
467 memset(old_pw
, 0, sizeof(old_pw
));
472 siad_chg_password (sia_collect_func_t
*collect
,
473 const char *username
,
480 char new_pw1
[MAX_KPW_LEN
+1];
481 char new_pw2
[MAX_KPW_LEN
+1];
482 static struct et_list
*et_list
;
484 set_progname(argv
[0]);
486 SIA_DEBUG(("DEBUG", "siad_chg_password"));
491 username
= getlogin();
493 ret
= krb_parse_name(username
, &princ
);
496 if(princ
.realm
[0] == '\0')
497 krb_get_lrealm(princ
.realm
, 1);
499 if(et_list
== NULL
) {
500 initialize_kadm_error_table_r(&et_list
);
501 initialize_krb_error_table_r(&et_list
);
504 ret
= init_change(collect
, &princ
);
505 if(ret
!= SIADSUCCESS
)
509 prompts
[0].prompt
= (unsigned char*)"New password: ";
510 prompts
[0].result
= (unsigned char*)new_pw1
;
511 prompts
[0].min_result_length
= MIN_KPW_LEN
;
512 prompts
[0].max_result_length
= sizeof(new_pw1
) - 1;
513 prompts
[0].control_flags
= SIARESINVIS
;
514 prompts
[1].prompt
= (unsigned char*)"Verify new password: ";
515 prompts
[1].result
= (unsigned char*)new_pw2
;
516 prompts
[1].min_result_length
= MIN_KPW_LEN
;
517 prompts
[1].max_result_length
= sizeof(new_pw2
) - 1;
518 prompts
[1].control_flags
= SIARESINVIS
;
519 if((*collect
)(120, SIAFORM
, (unsigned char*)"", 2, prompts
) !=
524 if(strcmp(new_pw1
, new_pw2
) != 0){
525 sia_message(collect
, SIAWARNING
, "", "Password mismatch.");
528 ret
= kadm_check_pw(new_pw1
);
530 sia_message(collect
, SIAWARNING
, "", com_right(et_list
, ret
));
534 memset(new_pw2
, 0, sizeof(new_pw2
));
535 ret
= kadm_init_link (PWSERV_NAME
, KRB_MASTER
, princ
.realm
);
536 if (ret
!= KADM_SUCCESS
)
537 sia_message(collect
, SIAWARNING
, "Error initing kadmin connection",
538 com_right(et_list
, ret
));
541 char *pw_msg
; /* message from server */
543 des_string_to_key(new_pw1
, &newkey
);
544 ret
= kadm_change_pw_plain((unsigned char*)&newkey
, new_pw1
, &pw_msg
);
545 memset(newkey
, 0, sizeof(newkey
));
547 if (ret
== KADM_INSECURE_PW
)
548 sia_message(collect
, SIAWARNING
, "Insecure password", pw_msg
);
549 else if (ret
!= KADM_SUCCESS
)
550 sia_message(collect
, SIAWARNING
, "Error changing password",
551 com_right(et_list
, ret
));
553 memset(new_pw1
, 0, sizeof(new_pw1
));
555 if (ret
!= KADM_SUCCESS
)
556 sia_message(collect
, SIAWARNING
, "", "Password NOT changed.");
558 sia_message(collect
, SIAINFO
, "", "Password changed.");
567 siad_chg_shell (sia_collect_func_t
*collect
,
568 const char *username
,
576 siad_getpwent(struct passwd
*result
,
579 struct sia_context
*context
)
585 siad_getpwuid (uid_t uid
,
586 struct passwd
*result
,
589 struct sia_context
*context
)
595 siad_getpwnam (const char *name
,
596 struct passwd
*result
,
599 struct sia_context
*context
)
605 siad_setpwent (struct sia_context
*context
)
611 siad_endpwent (struct sia_context
*context
)
617 siad_getgrent(struct group
*result
,
620 struct sia_context
*context
)
626 siad_getgrgid (gid_t gid
,
627 struct group
*result
,
630 struct sia_context
*context
)
636 siad_getgrnam (const char *name
,
637 struct group
*result
,
640 struct sia_context
*context
)
646 siad_setgrent (struct sia_context
*context
)
652 siad_endgrent (struct sia_context
*context
)
658 siad_chk_user (const char *logname
, int checkflag
)
660 if(checkflag
!= CHGPASSWD
)