Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / heimdal / appl / login / login.c
1 /*
2  * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden). 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met: 
9  *
10  * 1. Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer. 
12  *
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. 
16  *
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. 
20  *
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 
31  * SUCH DAMAGE. 
32  */
33
34 #include "login_locl.h"
35 #ifdef HAVE_CAPABILITY_H
36 #include <capability.h>
37 #endif
38 #ifdef HAVE_SYS_CAPABILITY_H
39 #include <sys/capability.h>
40 #endif
41
42 RCSID("$Id: login.c,v 1.56 2002/08/23 12:11:09 joda Exp $");
43
44 static int login_timeout = 60;
45
46 static int
47 start_login_process(void)
48 {
49     char *prog, *argv0;
50     prog = login_conf_get_string("login_program");
51     if(prog == NULL)
52         return 0;
53     argv0 = strrchr(prog, '/');
54
55     if(argv0)
56         argv0++;
57     else
58         argv0 = prog;
59
60     return simple_execle(prog, argv0, NULL, env);
61 }
62
63 static int
64 start_logout_process(void)
65 {
66     char *prog, *argv0;
67     pid_t pid;
68
69     prog = login_conf_get_string("logout_program");
70     if(prog == NULL)
71         return 0;
72     argv0 = strrchr(prog, '/');
73
74     if(argv0)
75         argv0++;
76     else
77         argv0 = prog;
78
79     pid = fork();
80     if(pid == 0) {
81         /* avoid getting signals sent to the shell */
82         setpgid(0, getpid());
83         return 0;
84     }
85     if(pid == -1)
86         err(1, "fork");
87     /* wait for the real login process to exit */
88 #ifdef HAVE_SETPROCTITLE
89     setproctitle("waitpid %d", pid);
90 #endif
91     while(1) {
92         int status;
93         int ret;
94         ret = waitpid(pid, &status, 0);
95         if(ret > 0) {
96             if(WIFEXITED(status) || WIFSIGNALED(status)) {
97                 execle(prog, argv0, NULL, env);
98                 err(1, "exec %s", prog);
99             }
100         } else if(ret < 0) 
101             err(1, "waitpid");
102     }
103 }
104
105 static void
106 exec_shell(const char *shell, int fallback)
107 {
108     char *sh;
109     const char *p;
110     
111     extend_env(NULL);
112     if(start_login_process() < 0)
113         warn("login process");
114     start_logout_process();
115
116     p = strrchr(shell, '/');
117     if(p)
118         p++;
119     else
120         p = shell;
121     asprintf(&sh, "-%s", p);
122     execle(shell, sh, NULL, env);
123     if(fallback){
124         warnx("Can't exec %s, trying %s", 
125               shell, _PATH_BSHELL);
126         execle(_PATH_BSHELL, "-sh", NULL, env);
127         err(1, "%s", _PATH_BSHELL);
128     }
129     err(1, "%s", shell);
130 }
131
132 static enum { NONE = 0, AUTH_KRB4 = 1, AUTH_KRB5 = 2, AUTH_OTP = 3 } auth;
133
134 #ifdef OTP
135 static OtpContext otp_ctx;
136
137 static int
138 otp_verify(struct passwd *pwd, const char *password)
139 {
140    return (otp_verify_user (&otp_ctx, password));
141 }
142 #endif /* OTP */
143
144
145 #ifdef KRB4
146 static int pag_set = 0;
147 #endif
148
149 #ifdef KRB5
150 static krb5_context context;
151 static krb5_ccache  id, id2;
152
153 static int
154 krb5_verify(struct passwd *pwd, const char *password)
155 {
156     krb5_error_code ret;
157     krb5_principal princ;
158
159     ret = krb5_parse_name(context, pwd->pw_name, &princ);
160     if(ret)
161         return 1;
162     ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
163     if(ret) {
164         krb5_free_principal(context, princ);
165         return 1;
166     }
167     ret = krb5_verify_user_lrealm(context,
168                                   princ, 
169                                   id,
170                                   password, 
171                                   1,
172                                   NULL);
173     krb5_free_principal(context, princ);
174     return ret;
175 }
176
177 #ifdef KRB4
178 static krb5_error_code
179 krb5_to4 (krb5_ccache id)
180 {
181     krb5_error_code ret;
182     krb5_principal princ;
183
184     int get_v4_tgt;
185
186     get_v4_tgt = krb5_config_get_bool(context, NULL,
187                                       "libdefaults",
188                                       "krb4_get_tickets",
189                                       NULL);
190
191     ret = krb5_cc_get_principal(context, id, &princ);
192     if (ret == 0) {
193         get_v4_tgt = krb5_config_get_bool_default(context, NULL,
194                                                   get_v4_tgt,
195                                                   "realms",
196                                                   *krb5_princ_realm(context,
197                                                                     princ),
198                                                   "krb4_get_tickets",
199                                                   NULL);
200         krb5_free_principal(context, princ);
201     }
202
203     if (get_v4_tgt) {
204         CREDENTIALS c;
205         krb5_creds mcred, cred;
206         char krb4tkfile[MAXPATHLEN];
207         krb5_error_code ret;
208         krb5_principal princ;
209
210         ret = krb5_cc_get_principal (context, id, &princ);
211         if (ret)
212             return ret;
213
214         ret = krb5_make_principal(context, &mcred.server,
215                                   princ->realm,
216                                   "krbtgt",
217                                   princ->realm,
218                                   NULL);
219         krb5_free_principal (context, princ);
220         if (ret)
221             return ret;
222
223         ret = krb5_cc_retrieve_cred(context, id, 0, &mcred, &cred);
224         if(ret == 0) {
225             ret = krb524_convert_creds_kdc_ccache(context, id, &cred, &c);
226             if(ret == 0) {
227                 snprintf(krb4tkfile,sizeof(krb4tkfile),"%s%d",TKT_ROOT,
228                          getuid());
229                 krb_set_tkt_string(krb4tkfile);
230                 tf_setup(&c, c.pname, c.pinst);
231             }
232             memset(&c, 0, sizeof(c));
233             krb5_free_creds_contents(context, &cred);
234         }
235         krb5_free_principal(context, mcred.server);
236     }
237     return 0;
238 }
239 #endif /* KRB4 */
240
241 static int
242 krb5_start_session (const struct passwd *pwd)
243 {
244     krb5_error_code ret;
245     char residual[64];
246
247     /* copy credentials to file cache */
248     snprintf(residual, sizeof(residual), "FILE:/tmp/krb5cc_%u", 
249              (unsigned)pwd->pw_uid);
250     krb5_cc_resolve(context, residual, &id2);
251     ret = krb5_cc_copy_cache(context, id, id2);
252     if (ret == 0)
253         add_env("KRB5CCNAME", residual);
254     else {
255         krb5_cc_destroy (context, id2);
256         return ret;
257     }
258 #ifdef KRB4
259     krb5_to4 (id2);
260 #endif
261     krb5_cc_close(context, id2);
262     krb5_cc_destroy(context, id);
263     return 0;
264 }
265
266 static void
267 krb5_finish (void)
268 {
269     krb5_free_context(context);
270 }
271
272 #ifdef KRB4
273
274 static void
275 krb5_get_afs_tokens (const struct passwd *pwd)
276 {
277     char cell[64];
278     char *pw_dir;
279     krb5_error_code ret;
280
281     if (!k_hasafs ())
282         return;
283
284     ret = krb5_cc_default(context, &id2);
285  
286     if (ret == 0) {
287         pw_dir = pwd->pw_dir;
288
289         if (!pag_set) {
290             k_setpag();
291             pag_set = 1;
292         }
293
294         if(k_afs_cell_of_file(pw_dir, cell, sizeof(cell)) == 0)
295             krb5_afslog_uid_home (context, id2,
296                                   cell, NULL, pwd->pw_uid, pwd->pw_dir);
297         krb5_afslog_uid_home (context, id2, NULL, NULL,
298                               pwd->pw_uid, pwd->pw_dir);
299         krb5_cc_close (context, id2);
300     }
301 }
302
303 #endif /* KRB4 */
304
305 #endif /* KRB5 */
306
307 #ifdef KRB4
308
309 static int
310 krb4_verify(struct passwd *pwd, const char *password)
311 {
312     char lrealm[REALM_SZ];
313     int ret;
314     char ticket_file[MaxPathLen];
315
316     ret = krb_get_lrealm (lrealm, 1);
317     if (ret)
318         return 1;
319
320     snprintf (ticket_file, sizeof(ticket_file),
321               "%s%u_%u",
322               TKT_ROOT, (unsigned)pwd->pw_uid, (unsigned)getpid());
323
324     krb_set_tkt_string (ticket_file);
325
326     ret = krb_verify_user (pwd->pw_name, "", lrealm, (char *)password,
327                            KRB_VERIFY_SECURE_FAIL, NULL);
328     if (ret)
329         return 1;
330
331     if (chown (ticket_file, pwd->pw_uid, pwd->pw_gid) < 0) {
332         dest_tkt();
333         return 1;
334     }
335         
336     add_env ("KRBTKFILE", ticket_file);
337     return 0;
338 }
339
340 static void
341 krb4_get_afs_tokens (const struct passwd *pwd)
342 {
343     char cell[64];
344     char *pw_dir;
345
346     if (!k_hasafs ())
347         return;
348
349     pw_dir = pwd->pw_dir;
350
351     if (!pag_set) {
352         k_setpag();
353         pag_set = 1;
354     }
355
356     if(k_afs_cell_of_file(pw_dir, cell, sizeof(cell)) == 0)
357         krb_afslog_uid_home (cell, NULL, pwd->pw_uid, pwd->pw_dir);
358
359     krb_afslog_uid_home (NULL, NULL, pwd->pw_uid, pwd->pw_dir);
360 }
361
362 #endif /* KRB4 */
363
364 static int f_flag;
365 static int p_flag;
366 #if 0
367 static int r_flag;
368 #endif
369 static int version_flag;
370 static int help_flag;
371 static char *remote_host;
372 static char *auth_level = NULL;
373
374 struct getargs args[] = {
375     { NULL, 'a', arg_string,    &auth_level,    "authentication mode" },
376 #if 0
377     { NULL, 'd' },
378 #endif
379     { NULL, 'f', arg_flag,      &f_flag,        "pre-authenticated" },
380     { NULL, 'h', arg_string,    &remote_host,   "remote host", "hostname" },
381     { NULL, 'p', arg_flag,      &p_flag,        "don't purge environment" },
382 #if 0
383     { NULL, 'r', arg_flag,      &r_flag,        "rlogin protocol" },
384 #endif
385     { "version", 0,  arg_flag,  &version_flag },
386     { "help",    0,  arg_flag,&help_flag, }
387 };
388
389 int nargs = sizeof(args) / sizeof(args[0]);
390
391 static void
392 update_utmp(const char *username, const char *hostname,
393             char *tty, char *ttyn)
394 {
395     /*
396      * Update the utmp files, both BSD and SYSV style.
397      */
398     if (utmpx_login(tty, username, hostname) != 0 && !f_flag) {
399         printf("No utmpx entry.  You must exec \"login\" from the "
400                "lowest level shell.\n");
401         exit(1);
402     }
403     utmp_login(ttyn, username, hostname);
404 }
405
406 static void
407 checknologin(void)
408 {
409     FILE *f;
410     char buf[1024];
411
412     f = fopen(_PATH_NOLOGIN, "r");
413     if(f == NULL)
414         return;
415     while(fgets(buf, sizeof(buf), f))
416         fputs(buf, stdout);
417     fclose(f);
418     exit(0);
419 }
420
421 /* print contents of a file */
422 static void
423 show_file(const char *file)
424 {
425     FILE *f;
426     char buf[BUFSIZ];
427     if((f = fopen(file, "r")) == NULL)
428         return;
429     while (fgets(buf, sizeof(buf), f))
430         fputs(buf, stdout);
431     fclose(f);
432 }
433
434 /* 
435  * Actually log in the user.  `pwd' contains all the relevant
436  * information about the user.  `ttyn' is the complete name of the tty
437  * and `tty' the short name.
438  */
439
440 static void
441 do_login(const struct passwd *pwd, char *tty, char *ttyn)
442 {
443 #ifdef HAVE_GETSPNAM
444     struct spwd *sp;
445 #endif
446     int rootlogin = (pwd->pw_uid == 0);
447     gid_t tty_gid;
448     struct group *gr;
449     const char *home_dir;
450     int i;
451
452     if(!rootlogin)
453         checknologin();
454     
455 #ifdef HAVE_GETSPNAM
456     sp = getspnam(pwd->pw_name);
457 #endif
458
459     update_utmp(pwd->pw_name, remote_host ? remote_host : "",
460                 tty, ttyn);
461
462     gr = getgrnam ("tty");
463     if (gr != NULL)
464         tty_gid = gr->gr_gid;
465     else
466         tty_gid = pwd->pw_gid;
467
468     if (chown (ttyn, pwd->pw_uid, tty_gid) < 0) {
469         warn("chown %s", ttyn);
470         if (rootlogin == 0)
471             exit (1);
472     }
473
474     if (chmod (ttyn, S_IRUSR | S_IWUSR | S_IWGRP) < 0) {
475         warn("chmod %s", ttyn);
476         if (rootlogin == 0)
477             exit (1);
478     }
479
480 #ifdef HAVE_SETLOGIN
481     if(setlogin(pwd->pw_name)){
482         warn("setlogin(%s)", pwd->pw_name);
483         if(rootlogin == 0)
484             exit(1);
485     }
486 #endif
487 #ifdef HAVE_SETPCRED
488     if (setpcred (pwd->pw_name, NULL) == -1)
489         warn("setpcred(%s)", pwd->pw_name);
490 #endif /* HAVE_SETPCRED */
491 #ifdef HAVE_INITGROUPS
492     if(initgroups(pwd->pw_name, pwd->pw_gid)){
493         warn("initgroups(%s, %u)", pwd->pw_name, (unsigned)pwd->pw_gid);
494         if(rootlogin == 0)
495             exit(1);
496     }
497 #endif
498     if(do_osfc2_magic(pwd->pw_uid))
499         exit(1);
500     if(setgid(pwd->pw_gid)){
501         warn("setgid(%u)", (unsigned)pwd->pw_gid);
502         if(rootlogin == 0)
503             exit(1);
504     }
505     if(setuid(pwd->pw_uid) || (pwd->pw_uid != 0 && setuid(0) == 0)) {
506         warn("setuid(%u)", (unsigned)pwd->pw_uid);
507         if(rootlogin == 0)
508             exit(1);
509     }
510
511     /* make sure signals are set to default actions, apparently some
512        OS:es like to ignore SIGINT, which is not very convenient */
513     
514     for (i = 1; i < NSIG; ++i)
515         signal(i, SIG_DFL);
516
517     /* all kinds of different magic */
518
519 #ifdef HAVE_GETSPNAM
520     check_shadow(pwd, sp);
521 #endif
522
523 #if defined(HAVE_GETUDBNAM) && defined(HAVE_SETLIM)
524     {
525         struct udb *udb;
526         long t;
527         const long maxcpu = 46116860184; /* some random constant */
528         udb = getudbnam(pwd->pw_name);
529         if(udb == UDB_NULL)
530             errx(1, "Failed to get UDB entry.");
531         t = udb->ue_pcpulim[UDBRC_INTER];
532         if(t == 0 || t > maxcpu)
533             t = CPUUNLIM;
534         else
535             t *= 100 * CLOCKS_PER_SEC;
536
537         if(limit(C_PROC, 0, L_CPU, t) < 0)
538             warn("limit C_PROC");
539
540         t = udb->ue_jcpulim[UDBRC_INTER];
541         if(t == 0 || t > maxcpu)
542             t = CPUUNLIM;
543         else
544             t *= 100 * CLOCKS_PER_SEC;
545
546         if(limit(C_JOBPROCS, 0, L_CPU, t) < 0)
547             warn("limit C_JOBPROCS");
548
549         nice(udb->ue_nice[UDBRC_INTER]);
550     }
551 #endif
552 #if defined(HAVE_SGI_GETCAPABILITYBYNAME) && defined(HAVE_CAP_SET_PROC)
553         /* XXX SGI capability hack IRIX 6.x (x >= 0?) has something
554            called capabilities, that allow you to give away
555            permissions (such as chown) to specific processes. From 6.5
556            this is default on, and the default capability set seems to
557            not always be the empty set. The problem is that the
558            runtime linker refuses to do just about anything if the
559            process has *any* capabilities set, so we have to remove
560            them here (unless otherwise instructed by /etc/capability).
561            In IRIX < 6.5, these functions was called sgi_cap_setproc,
562            etc, but we ignore this fact (it works anyway). */
563         {
564             struct user_cap *ucap = sgi_getcapabilitybyname(pwd->pw_name);
565             cap_t cap;
566             if(ucap == NULL)
567                 cap = cap_from_text("all=");
568             else
569                 cap = cap_from_text(ucap->ca_default);
570             if(cap == NULL)
571                 err(1, "cap_from_text");
572             if(cap_set_proc(cap) < 0)
573                 err(1, "cap_set_proc");
574             cap_free(cap);
575             free(ucap);
576         }
577 #endif
578     home_dir = pwd->pw_dir;
579     if (chdir(home_dir) < 0) {
580         fprintf(stderr, "No home directory \"%s\"!\n", pwd->pw_dir);
581         if (chdir("/"))
582             exit(0);
583         home_dir = "/";
584         fprintf(stderr, "Logging in with home = \"/\".\n");
585     }
586 #ifdef KRB5
587     if (auth == AUTH_KRB5) {
588         krb5_start_session (pwd);
589     }
590 #ifdef KRB4
591     else if (auth == 0) {
592         krb5_error_code ret;
593         krb5_ccache id;
594
595         ret = krb5_cc_default (context, &id);
596         if (ret == 0) {
597             krb5_to4 (id);
598             krb5_cc_close (context, id);
599         }
600     }
601
602     krb5_get_afs_tokens (pwd);
603 #endif /* KRB4 */
604     krb5_finish ();
605 #endif /* KRB5 */
606
607 #ifdef KRB4
608     krb4_get_afs_tokens (pwd);
609 #endif /* KRB4 */
610
611     add_env("PATH", _PATH_DEFPATH);
612
613     {
614         const char *str = login_conf_get_string("environment");
615         char buf[MAXPATHLEN];
616
617         if(str == NULL) {
618             login_read_env(_PATH_ETC_ENVIRONMENT);
619         } else {
620             while(strsep_copy(&str, ",", buf, sizeof(buf)) != -1) {
621                 if(buf[0] == '\0')
622                     continue;
623                 login_read_env(buf);
624             }
625         }
626     }
627     {
628         const char *str = login_conf_get_string("motd");
629         char buf[MAXPATHLEN];
630
631         if(str != NULL) {
632             while(strsep_copy(&str, ",", buf, sizeof(buf)) != -1) {
633                 if(buf[0] == '\0')
634                     continue;
635                 show_file(buf);
636             }
637         }
638     }
639     add_env("HOME", home_dir);
640     add_env("USER", pwd->pw_name);
641     add_env("LOGNAME", pwd->pw_name);
642     add_env("SHELL", pwd->pw_shell);
643     exec_shell(pwd->pw_shell, rootlogin);
644 }
645
646 static int
647 check_password(struct passwd *pwd, const char *password)
648 {
649     if(pwd->pw_passwd == NULL)
650         return 1;
651     if(pwd->pw_passwd[0] == '\0'){
652 #ifdef ALLOW_NULL_PASSWORD
653         return password[0] != '\0';
654 #else
655         return 1;
656 #endif
657     }
658     if(strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) == 0)
659         return 0;
660 #ifdef KRB5
661     if(krb5_verify(pwd, password) == 0) {
662         auth = AUTH_KRB5;
663         return 0;
664     }
665 #endif
666 #ifdef KRB4
667     if (krb4_verify (pwd, password) == 0) {
668         auth = AUTH_KRB4;
669         return 0;
670     }
671 #endif
672 #ifdef OTP
673     if (otp_verify (pwd, password) == 0) {
674        auth = AUTH_OTP;
675        return 0;
676     }
677 #endif
678     return 1;
679 }
680
681 static void
682 usage(int status)
683 {
684     arg_printusage(args, nargs, NULL, "[username]");
685     exit(status);
686 }
687
688 static RETSIGTYPE
689 sig_handler(int sig)
690 {
691     if (sig == SIGALRM)
692          fprintf(stderr, "Login timed out after %d seconds\n",
693                 login_timeout);
694       else
695          fprintf(stderr, "Login received signal, exiting\n");
696     exit(0);
697 }
698
699 int
700 main(int argc, char **argv)
701 {
702     int max_tries = 5;
703     int try;
704
705     char username[32];
706     int optind = 0;
707
708     int ask = 1;
709     struct sigaction sa;
710     
711     setprogname(argv[0]);
712
713 #ifdef KRB5
714     {
715         krb5_error_code ret;
716
717         ret = krb5_init_context(&context);
718         if (ret)
719             errx (1, "krb5_init_context failed: %d", ret);
720     }
721 #endif
722
723     openlog("login", LOG_ODELAY, LOG_AUTH);
724
725     if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
726                 &optind))
727         usage (1);
728     argc -= optind;
729     argv += optind;
730
731     if(help_flag)
732         usage(0);
733     if (version_flag) {
734         print_version (NULL);
735         return 0;
736     }
737         
738     if (geteuid() != 0)
739         errx(1, "only root may use login, use su");
740
741     /* Default tty settings. */
742     stty_default();
743
744     if(p_flag)
745         copy_env();
746     else {
747         /* this set of variables is always preserved by BSD login */
748         if(getenv("TERM"))
749             add_env("TERM", getenv("TERM"));
750         if(getenv("TZ"))
751             add_env("TZ", getenv("TZ"));
752     }
753
754     if(*argv){
755         if(strchr(*argv, '=') == NULL && strcmp(*argv, "-") != 0){
756             strlcpy (username, *argv, sizeof(username));
757             ask = 0;
758         }
759     }
760
761 #if defined(DCE) && defined(AIX)
762     esetenv("AUTHSTATE", "DCE", 1);
763 #endif
764
765     /* XXX should we care about environment on the command line? */
766
767     memset(&sa, 0, sizeof(sa));
768     sa.sa_handler = sig_handler;
769     sigemptyset(&sa.sa_mask);
770     sa.sa_flags = 0;
771     sigaction(SIGALRM, &sa, NULL);
772     alarm(login_timeout);
773
774     for(try = 0; try < max_tries; try++){
775         struct passwd *pwd;
776         char password[128];
777         int ret;
778         char ttname[32];
779         char *tty, *ttyn;
780         char prompt[128];
781 #ifdef OTP
782         char otp_str[256];
783 #endif
784
785         if(ask){
786             f_flag = 0;
787 #if 0
788             r_flag = 0;
789 #endif
790             ret = read_string("login: ", username, sizeof(username), 1);
791             if(ret == -3)
792                 exit(0);
793             if(ret == -2)
794                 sig_handler(0); /* exit */
795         }
796         pwd = k_getpwnam(username);
797 #ifdef ALLOW_NULL_PASSWORD
798         if (pwd != NULL && (pwd->pw_passwd[0] == '\0')) {
799             strcpy(password,"");
800         }
801         else
802 #endif
803
804         {
805 #ifdef OTP
806            if(auth_level && strcmp(auth_level, "otp") == 0 &&
807                  otp_challenge(&otp_ctx, username,
808                             otp_str, sizeof(otp_str)) == 0)
809                  snprintf (prompt, sizeof(prompt), "%s's %s Password: ",
810                             username, otp_str);
811             else
812 #endif
813                  strncpy(prompt, "Password: ", sizeof(prompt));
814
815             if (f_flag == 0) {
816                ret = read_string(prompt, password, sizeof(password), 0);
817                if (ret == -3) {
818                   ask = 1;
819                   continue;
820                }
821                if (ret == -2)
822                   sig_handler(0);
823             }
824          }
825         
826         if(pwd == NULL){
827             fprintf(stderr, "Login incorrect.\n");
828             ask = 1;
829             continue;
830         }
831
832         if(f_flag == 0 && check_password(pwd, password)){
833             fprintf(stderr, "Login incorrect.\n");
834             ask = 1;
835             continue;
836         }
837         ttyn = ttyname(STDIN_FILENO);
838         if(ttyn == NULL){
839             snprintf(ttname, sizeof(ttname), "%s??", _PATH_TTY);
840             ttyn = ttname;
841         }
842         if (strncmp (ttyn, _PATH_DEV, strlen(_PATH_DEV)) == 0)
843             tty = ttyn + strlen(_PATH_DEV);
844         else
845             tty = ttyn;
846     
847         if (login_access (pwd, remote_host ? remote_host : tty) == 0) {
848             fprintf(stderr, "Permission denied\n");
849             if (remote_host)
850                 syslog(LOG_NOTICE, "%s LOGIN REFUSED FROM %s",
851                        pwd->pw_name, remote_host);
852             else
853                 syslog(LOG_NOTICE, "%s LOGIN REFUSED ON %s",
854                        pwd->pw_name, tty);
855             exit (1);
856         }
857         alarm(0);
858         do_login(pwd, tty, ttyn);
859     }
860     exit(1);
861 }