2 * Copyright (c) 1995-2001 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. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 siad_chk_invoker(void)
47 SIA_DEBUG(("DEBUG", "siad_chk_invoker"));
52 siad_ses_init(SIAENTITY
*entity
, int pkgind
)
54 struct state
*s
= malloc(sizeof(*s
));
56 SIA_DEBUG(("DEBUG", "siad_ses_init"));
59 memset(s
, 0, sizeof(*s
));
63 ret
= krb5_init_context(&s
->context
);
68 entity
->mech
[pkgind
] = (int*)s
;
73 setup_name(SIAENTITY
*e
, prompt_t
*p
)
75 SIA_DEBUG(("DEBUG", "setup_name"));
76 e
->name
= malloc(SIANAMEMIN
+ 1);
78 SIA_DEBUG(("DEBUG", "failed to malloc %u bytes", SIANAMEMIN
+1));
81 p
->prompt
= (unsigned char*)"login: ";
82 p
->result
= (unsigned char*)e
->name
;
83 p
->min_result_length
= 1;
84 p
->max_result_length
= SIANAMEMIN
;
90 setup_password(SIAENTITY
*e
, prompt_t
*p
)
92 SIA_DEBUG(("DEBUG", "setup_password"));
93 e
->password
= malloc(SIAMXPASSWORD
+ 1);
94 if(e
->password
== NULL
){
95 SIA_DEBUG(("DEBUG", "failed to malloc %u bytes", SIAMXPASSWORD
+1));
98 p
->prompt
= (unsigned char*)"Password: ";
99 p
->result
= (unsigned char*)e
->password
;
100 p
->min_result_length
= 0;
101 p
->max_result_length
= SIAMXPASSWORD
;
102 p
->control_flags
= SIARESINVIS
;
108 doauth(SIAENTITY
*entity
, int pkgind
, char *name
)
110 struct passwd pw
, *pwd
;
112 struct state
*s
= (struct state
*)entity
->mech
[pkgind
];
114 krb5_realm
*realms
, *r
;
115 krb5_principal principal
;
120 char realm
[REALM_SZ
];
121 char *toname
, *toinst
;
123 struct passwd fpw
, *fpwd
;
128 if(getpwnam_r(name
, &pw
, pwbuf
, sizeof(pwbuf
), &pwd
) != 0){
129 SIA_DEBUG(("DEBUG", "failed to getpwnam(%s)", name
));
134 ret
= krb5_get_default_realms(s
->context
, &realms
);
136 for (r
= realms
; *r
!= NULL
; ++r
) {
137 krb5_make_principal (s
->context
, &principal
, *r
, entity
->name
, NULL
);
139 if(krb5_kuserok(s
->context
, principal
, entity
->name
))
142 krb5_free_host_realm (s
->context
, realms
);
146 sprintf(s
->ticket
, "FILE:/tmp/krb5_cc%d_%d", pwd
->pw_uid
, getpid());
147 ret
= krb5_cc_resolve(s
->context
, s
->ticket
, &ccache
);
153 snprintf(s
->ticket
, sizeof(s
->ticket
),
154 "%s%u_%u", TKT_ROOT
, (unsigned)pwd
->pw_uid
, (unsigned)getpid());
155 krb_get_lrealm(realm
, 1);
158 if(entity
->authtype
== SIA_A_SUAUTH
){
160 #ifdef HAVE_SIAENTITY_OUID
165 if(getpwuid_r(ouid
, &fpw
, fpwbuf
, sizeof(fpwbuf
), &fpwd
) != 0){
166 SIA_DEBUG(("DEBUG", "failed to getpwuid(%u)", ouid
));
169 snprintf(s
->ticket
, sizeof(s
->ticket
), "%s_%s_to_%s_%d",
170 TKT_ROOT
, fpwd
->pw_name
, pwd
->pw_name
, getpid());
171 if(strcmp(pwd
->pw_name
, "root") == 0){
172 toname
= fpwd
->pw_name
;
173 toinst
= pwd
->pw_name
;
176 if(entity
->authtype
== SIA_A_REAUTH
)
177 snprintf(s
->ticket
, sizeof(s
->ticket
), "%s", tkt_string());
179 krb_set_tkt_string(s
->ticket
);
181 setuid(0); /* XXX fix for fix in tf_util.c */
182 if(krb_kuserok(toname
, toinst
, realm
, name
)){
183 SIA_DEBUG(("DEBUG", "%s.%s@%s is not allowed to login as %s",
184 toname
, toinst
, realm
, name
));
189 ret
= krb5_verify_user_lrealm(s
->context
, principal
, ccache
,
190 entity
->password
, 1, NULL
);
192 /* if this is most likely a local user (such as
193 root), just silently return failure when the
194 principal doesn't exist */
195 if(ret
!= KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
&&
196 ret
!= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
)
197 SIALOG("WARNING", "krb5_verify_user(%s): %s",
198 entity
->name
, error_message(ret
));
204 secure
= KRB_VERIFY_SECURE
;
206 secure
= KRB_VERIFY_NOT_SECURE
;
208 ret
= krb_verify_user(toname
, toinst
, realm
,
209 entity
->password
, secure
, NULL
);
211 SIA_DEBUG(("DEBUG", "krb_verify_user: %s", krb_get_err_text(ret
)));
212 if(ret
!= KDC_PR_UNKNOWN
)
213 /* since this is most likely a local user (such as
214 root), just silently return failure when the
215 principal doesn't exist */
216 SIALOG("WARNING", "krb_verify_user(%s.%s): %s",
217 toname
, toinst
, krb_get_err_text(ret
));
221 if(sia_make_entity_pwd(pwd
, entity
) == SIAFAIL
)
229 common_auth(sia_collect_func_t
*collect
,
234 prompt_t prompts
[2], *pr
;
237 SIA_DEBUG(("DEBUG", "common_auth"));
238 if((siastat
== SIADSUCCESS
) && (geteuid() == 0))
241 SIA_DEBUG(("DEBUG", "entity == NULL"));
242 return SIADFAIL
| SIADSTOP
;
246 name
= entity
->acctname
;
248 if((collect
!= NULL
) && entity
->colinput
) {
252 if(setup_name(entity
, pr
) != SIADSUCCESS
)
256 if(entity
->password
== NULL
){
257 if(setup_password(entity
, pr
) != SIADSUCCESS
)
263 if((*collect
)(240, SIAONELINER
, (unsigned char*)"", num
,
264 prompts
) != SIACOLSUCCESS
){
265 SIA_DEBUG(("DEBUG", "collect failed"));
266 return SIADFAIL
| SIADSTOP
;
269 if((*collect
)(0, SIAFORM
, (unsigned char*)"", num
,
270 prompts
) != SIACOLSUCCESS
){
271 SIA_DEBUG(("DEBUG", "collect failed"));
272 return SIADFAIL
| SIADSTOP
;
278 if(name
== NULL
|| name
[0] == '\0'){
279 SIA_DEBUG(("DEBUG", "name is null"));
283 if(entity
->password
== NULL
|| strlen(entity
->password
) > SIAMXPASSWORD
){
284 SIA_DEBUG(("DEBUG", "entity->password is null"));
288 return doauth(entity
, pkgind
, name
);
293 siad_ses_authent(sia_collect_func_t
*collect
,
298 SIA_DEBUG(("DEBUG", "siad_ses_authent"));
299 return common_auth(collect
, entity
, siastat
, pkgind
);
303 siad_ses_estab(sia_collect_func_t
*collect
,
304 SIAENTITY
*entity
, int pkgind
)
306 SIA_DEBUG(("DEBUG", "siad_ses_estab"));
311 siad_ses_launch(sia_collect_func_t
*collect
,
315 static char env
[MaxPathLen
];
316 struct state
*s
= (struct state
*)entity
->mech
[pkgind
];
317 SIA_DEBUG(("DEBUG", "siad_ses_launch"));
320 chown(s
->ticket
+ sizeof("FILE:") - 1,
322 entity
->pwd
->pw_gid
);
323 snprintf(env
, sizeof(env
), "KRB5CCNAME=%s", s
->ticket
);
326 chown(s
->ticket
, entity
->pwd
->pw_uid
, entity
->pwd
->pw_gid
);
327 snprintf(env
, sizeof(env
), "KRBTKFILE=%s", s
->ticket
);
335 if(k_afs_cell_of_file(entity
->pwd
->pw_dir
, cell
, sizeof(cell
)) == 0)
337 krb_afslog_home(0, 0, entity
->pwd
->pw_dir
);
344 siad_ses_release(SIAENTITY
*entity
, int pkgind
)
346 SIA_DEBUG(("DEBUG", "siad_ses_release"));
347 if(entity
->mech
[pkgind
]){
349 struct state
*s
= (struct state
*)entity
->mech
[pkgind
];
350 krb5_free_context(s
->context
);
352 free(entity
->mech
[pkgind
]);
358 siad_ses_suauthent(sia_collect_func_t
*collect
,
363 SIA_DEBUG(("DEBUG", "siad_ses_suauth"));
366 if(entity
->name
== NULL
)
368 if(entity
->name
[0] == '\0') {
370 entity
->name
= strdup("root");
371 if (entity
->name
== NULL
)
374 return common_auth(collect
, entity
, siastat
, pkgind
);
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
);
396 if(k_afs_cell_of_file(entity
->pwd
->pw_dir
,
397 cell
, sizeof(cell
)) == 0)
399 krb_afslog_home(0, 0, entity
->pwd
->pw_dir
);
407 siad_chg_finger (sia_collect_func_t
*collect
,
408 const char *username
,
412 SIA_DEBUG(("DEBUG", "siad_chg_finger"));
418 siad_chg_password (sia_collect_func_t
*collect
,
419 const char *username
,
429 sia_message(sia_collect_func_t
*collect
, int rendition
,
430 const char *title
, const char *message
)
433 prompt
.prompt
= (unsigned char*)message
;
434 (*collect
)(0, rendition
, (unsigned char*)title
, 1, &prompt
);
438 init_change(sia_collect_func_t
*collect
, krb_principal
*princ
)
441 char old_pw
[MAX_KPW_LEN
+1];
446 SIA_DEBUG(("DEBUG", "init_change"));
447 prompt
.prompt
= (unsigned char*)"Old password: ";
448 prompt
.result
= (unsigned char*)old_pw
;
449 prompt
.min_result_length
= 0;
450 prompt
.max_result_length
= sizeof(old_pw
) - 1;
451 prompt
.control_flags
= SIARESINVIS
;
452 asprintf(&msg
, "Changing password for %s", krb_unparse_name(princ
));
454 SIA_DEBUG(("DEBUG", "out of memory"));
457 ret
= (*collect
)(60, SIAONELINER
, (unsigned char*)msg
, 1, &prompt
);
459 SIA_DEBUG(("DEBUG", "ret = %d", ret
));
460 if(ret
!= SIACOLSUCCESS
)
462 snprintf(tktstring
, sizeof(tktstring
),
463 "%s_cpw_%u", TKT_ROOT
, (unsigned)getpid());
464 krb_set_tkt_string(tktstring
);
466 ret
= krb_get_pw_in_tkt(princ
->name
, princ
->instance
, princ
->realm
,
467 PWSERV_NAME
, KADM_SINST
, 1, old_pw
);
468 if (ret
!= KSUCCESS
) {
469 SIA_DEBUG(("DEBUG", "krb_get_pw_in_tkt: %s", krb_get_err_text(ret
)));
470 if (ret
== INTK_BADPW
)
471 sia_message(collect
, SIAWARNING
, "", "Incorrect old password.");
473 sia_message(collect
, SIAWARNING
, "", "Kerberos error.");
474 memset(old_pw
, 0, sizeof(old_pw
));
477 if(chown(tktstring
, getuid(), -1) < 0){
481 memset(old_pw
, 0, sizeof(old_pw
));
486 siad_chg_password (sia_collect_func_t
*collect
,
487 const char *username
,
494 char new_pw1
[MAX_KPW_LEN
+1];
495 char new_pw2
[MAX_KPW_LEN
+1];
496 static struct et_list
*et_list
;
498 setprogname(argv
[0]);
500 SIA_DEBUG(("DEBUG", "siad_chg_password"));
505 username
= getlogin();
507 ret
= krb_parse_name(username
, &princ
);
510 if(princ
.realm
[0] == '\0')
511 krb_get_lrealm(princ
.realm
, 1);
513 if(et_list
== NULL
) {
514 initialize_kadm_error_table_r(&et_list
);
515 initialize_krb_error_table_r(&et_list
);
518 ret
= init_change(collect
, &princ
);
519 if(ret
!= SIADSUCCESS
)
523 prompts
[0].prompt
= (unsigned char*)"New password: ";
524 prompts
[0].result
= (unsigned char*)new_pw1
;
525 prompts
[0].min_result_length
= MIN_KPW_LEN
;
526 prompts
[0].max_result_length
= sizeof(new_pw1
) - 1;
527 prompts
[0].control_flags
= SIARESINVIS
;
528 prompts
[1].prompt
= (unsigned char*)"Verify new password: ";
529 prompts
[1].result
= (unsigned char*)new_pw2
;
530 prompts
[1].min_result_length
= MIN_KPW_LEN
;
531 prompts
[1].max_result_length
= sizeof(new_pw2
) - 1;
532 prompts
[1].control_flags
= SIARESINVIS
;
533 if((*collect
)(120, SIAFORM
, (unsigned char*)"", 2, prompts
) !=
538 if(strcmp(new_pw1
, new_pw2
) != 0){
539 sia_message(collect
, SIAWARNING
, "", "Password mismatch.");
542 ret
= kadm_check_pw(new_pw1
);
544 sia_message(collect
, SIAWARNING
, "", com_right(et_list
, ret
));
548 memset(new_pw2
, 0, sizeof(new_pw2
));
549 ret
= kadm_init_link (PWSERV_NAME
, KRB_MASTER
, princ
.realm
);
550 if (ret
!= KADM_SUCCESS
)
551 sia_message(collect
, SIAWARNING
, "Error initing kadmin connection",
552 com_right(et_list
, ret
));
555 char *pw_msg
; /* message from server */
557 des_string_to_key(new_pw1
, &newkey
);
558 ret
= kadm_change_pw_plain((unsigned char*)&newkey
, new_pw1
, &pw_msg
);
559 memset(newkey
, 0, sizeof(newkey
));
561 if (ret
== KADM_INSECURE_PW
)
562 sia_message(collect
, SIAWARNING
, "Insecure password", pw_msg
);
563 else if (ret
!= KADM_SUCCESS
)
564 sia_message(collect
, SIAWARNING
, "Error changing password",
565 com_right(et_list
, ret
));
567 memset(new_pw1
, 0, sizeof(new_pw1
));
569 if (ret
!= KADM_SUCCESS
)
570 sia_message(collect
, SIAWARNING
, "", "Password NOT changed.");
572 sia_message(collect
, SIAINFO
, "", "Password changed.");
582 siad_chg_shell (sia_collect_func_t
*collect
,
583 const char *username
,
591 siad_getpwent(struct passwd
*result
,
594 struct sia_context
*context
)
600 siad_getpwuid (uid_t uid
,
601 struct passwd
*result
,
604 struct sia_context
*context
)
610 siad_getpwnam (const char *name
,
611 struct passwd
*result
,
614 struct sia_context
*context
)
620 siad_setpwent (struct sia_context
*context
)
626 siad_endpwent (struct sia_context
*context
)
632 siad_getgrent(struct group
*result
,
635 struct sia_context
*context
)
641 siad_getgrgid (gid_t gid
,
642 struct group
*result
,
645 struct sia_context
*context
)
651 siad_getgrnam (const char *name
,
652 struct group
*result
,
655 struct sia_context
*context
)
661 siad_setgrent (struct sia_context
*context
)
667 siad_endgrent (struct sia_context
*context
)
673 siad_chk_user (const char *logname
, int checkflag
)
675 if(checkflag
!= CHGPASSWD
)