source: trunk/athena/etc/ftpd/athena_ftpd.c @ 7831

Revision 7831, 22.2 KB checked in by cfields, 29 years ago (diff)
/etc/nocrack support. Security fix.
Line 
1#ifdef ATHENA
2#include <stdio.h>
3#ifdef POSIX
4#include <unistd.h>
5#endif
6#include <pwd.h>
7#ifdef SOLARIS
8#include <shadow.h>
9#include <signal.h>
10#endif
11#include <sys/file.h>
12#include <krb.h>
13#include <hesiod.h>
14#include <errno.h>
15#include <sys/types.h>
16#include <sys/stat.h>
17#ifdef SYSV
18#include <fcntl.h>
19#include <dirent.h>
20#else
21#include <sys/dir.h>
22#endif
23#include <sys/wait.h>
24#include <utmp.h>
25#ifdef _IBMR2
26#include <userpw.h>
27#include <usersec.h>
28#endif
29#include "athena_ftpd.h"
30#ifdef ultrix
31#include <sys/param.h>
32#include <sys/mount.h>
33#include <sys/fs_types.h>
34#endif
35#ifdef SYSV
36#include <sys/mkdev.h>
37#endif
38
39#define LOGIN_TKT_DEFAULT_LIFETIME DEFAULT_TKT_LIFE /* from krb.h */
40#define file_exists(f) (access((f), F_OK) == 0)
41
42#ifndef TRUE
43#define FALSE 0
44#define TRUE (!FALSE)
45#endif
46
47#define PASSWORD_LEN 14
48
49#define UTMPFILE "/etc/utmp"
50
51#ifndef NOLOGIN
52#define NOLOGIN "/etc/nologin"
53#endif
54#ifndef NOCREATE
55#define NOCREATE "/etc/nocreate"
56#endif
57#ifndef NOREMOTE
58#define NOREMOTE "/etc/noremote"
59#endif
60#ifndef NOATTACH
61#define NOATTACH "/etc/noattach"
62#endif
63#ifndef NOCRACK
64#define NOCRACK "/etc/nocrack"
65#endif
66
67#define ATTACH "/bin/athena/attach"
68#define DETACH "/bin/athena/detach"
69#define FSID "/bin/athena/fsid"
70#define UNLOG "/bin/athena/unlog"
71
72extern FILE *ftpd_popen();
73
74int athena_login = LOGIN_NONE;
75static int local_passwd;
76#ifdef _IBMR2
77static struct passwd athena_pwd = { "", "", 0, 0, "", "", "" };
78#else
79#ifdef ultrix
80static struct passwd athena_pwd = { "", "", 0, 0, 0, 0, 0, "", "", "", "" };
81#else
82static struct passwd athena_pwd = { "", "", 0, 0, 0, "", "", "", "" };
83#endif
84#endif
85static char att_errbuf[200];
86
87struct passwd *athena_getpwnam(user)
88     char *user;
89{
90  struct passwd *pwd;
91
92  if (!( /* If we already have looked this user up, don't do it again */
93        athena_pwd.pw_name && !strcmp(athena_pwd.pw_name, user) ))
94    {
95#ifdef SOLARIS
96      if ((pwd = get_pwnam(user)) != NULL)
97#else
98      if ((pwd = getpwnam(user)) != NULL)
99#endif
100        local_passwd = TRUE;
101      else
102        {
103          local_passwd = FALSE;
104          pwd = hes_getpwnam(user);
105          if (pwd == NULL || pwd->pw_dir[0] == 0)
106            pwd = NULL;
107        }
108
109      if (pwd)
110#ifdef POSIX
111        memmove(&athena_pwd, pwd, sizeof(struct passwd));
112#else
113        bcopy(pwd, &athena_pwd, sizeof(struct passwd));
114#endif
115      else
116        return NULL;
117    }
118
119  return &athena_pwd;
120}
121
122int athena_localpasswd(user)
123     char *user;
124{
125  struct passwd *pwd;
126
127  pwd = athena_getpwnam(user);
128  return local_passwd;
129}
130
131int athena_notallowed(user)
132     char *user;
133{
134  if ((!athena_localpasswd(user) &&
135       (file_exists(NOCREATE) || file_exists(NOREMOTE))) ||
136      file_exists(NOLOGIN))
137    return 1;
138  return 0;
139}
140
141int get_tickets(username, password)
142char *username;
143char *password;
144{
145    char inst[INST_SZ], realm[REALM_SZ];
146    int error;
147
148    /* inst has to be a buffer instead of the constant "" because
149     * krb_get_pw_in_tkt() will write a zero at inst[INST_SZ] to
150     * truncate it.
151     */
152    inst[0] = 0;
153    dest_tkt();
154
155    if (krb_get_lrealm(realm, 1) != KSUCCESS)
156      strcpy(realm, KRB_REALM);
157
158    error = krb_get_pw_in_tkt(username, inst, realm, "krbtgt", realm,
159                              LOGIN_TKT_DEFAULT_LIFETIME, password);
160
161    return error;
162}
163
164#ifndef WIFEXITED
165#define WIFEXITED(x)    (((union wait *)&(x))->w_stopval != WSTOPPED && \
166                         ((union wait *)&(x))->w_termsig == 0)
167#endif
168#ifndef WEXITSTATUS
169#define WEXITSTATUS(x)  (((union wait *)&(x))->w_retcode)
170#endif
171#define PEXITSTATUS(x)  ((x>>8) & 255)
172#ifdef SOLARIS
173remove_from_passwd(p)
174struct passwd *p;
175{
176    FILE *newfile;
177    struct passwd *copypw;
178    struct stat statb;
179    int cnt, fd;
180
181    cnt = 10;
182    while (cnt-- > 0 &&
183           (fd = open("/etc/ptmp", O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0)
184      sleep(1);
185    if (fd < 0) {
186        printf("Failed to remove you from /etc/passwd\n");
187    }
188    if ((newfile = fdopen(fd, "w")) != NULL) {
189        setpwent();
190        while ((copypw = getpwent()) != 0)
191            if (copypw->pw_uid != p->pw_uid)
192                    fprintf(newfile, "%s:%s:%d:%d:%s:%s:%s\n",
193                            copypw->pw_name,
194                            copypw->pw_passwd,
195                            copypw->pw_uid,
196                            copypw->pw_gid,
197                            copypw->pw_gecos,
198                            copypw->pw_dir,
199                            copypw->pw_shell);
200        endpwent();
201        fclose(newfile);
202        if (stat("/etc/ptmp", &statb) != 0 || statb.st_size < 80) {
203            printf("Failed to cleanup login\n");
204        } else
205          rename("/etc/ptmp", "/etc/passwd");
206        if (stat("/etc/passwd", &statb) != 0 || statb.st_size < 80) {
207            printf("Failed to cleanup login\n");
208            sleep(12);
209            if (stat("/etc/passwd", &statb) != 0 || statb.st_size < 80) {
210                newfile = fopen("/etc/passwd", "w");
211                fprintf(newfile, "root:x:0:1:System PRIVILEGED Account:/:/bin/csh\n");
212                fclose(newfile);
213            }
214        }
215      return(0);
216    }else return(1);
217}
218#endif
219
220#ifdef SOLARIS
221remove_from_shadow(pwd)
222struct passwd *pwd;
223{
224    FILE *newfile;
225    struct passwd *copypw;
226    struct spwd   *copyspw;
227    struct stat statb;
228    int cnt, fd;
229
230
231    cnt = 10;
232    while (cnt-- > 0 &&
233           (fd = open("/etc/ptmp", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0)
234      sleep(1);
235    if (fd < 0) {
236        printf("Failed to remove you from /etc/shadow\n");
237    }
238    if ((newfile = fdopen(fd, "w")) != NULL) {
239        setspent();
240        while ((copyspw = getspent()) != 0)
241            if (strcmp(copyspw->sp_namp , pwd->pw_name)) {
242                    fprintf(newfile, "%s:%s:%d::::::\n",
243                            copyspw->sp_namp,
244                            copyspw->sp_pwdp,
245                            copyspw->sp_lstchg);
246                  }
247        endspent();
248        fclose(newfile);
249        if (stat("/etc/ptmp", &statb) != 0 || statb.st_size < 80) {
250            printf("Failed to cleanup login\n");
251        } else
252          rename("/etc/ptmp", "/etc/shadow");
253        if (stat("/etc/shadow", &statb) != 0 || statb.st_size < 80) {
254            printf("Failed to cleanup login\n");
255            sleep(12);
256            if (stat("/etc/shadow", &statb) != 0 || statb.st_size < 80) {
257                newfile = fopen("/etc/shadow", "w");
258                fprintf(newfile, "root::6445::::::");
259                fclose(newfile);
260            }
261        }
262        return(0);
263    } else return(1);
264}
265#endif
266
267char *add_to_passwd(p)
268struct passwd *p;
269{
270    int i, fd = -1;
271#ifndef SOLARIS
272    FILE *etc_passwd;
273#else
274    FILE *etc_passwd, *etc_shadow;
275#endif
276    static char passerr[100];
277
278#ifdef _IBMR2
279    struct userpw pw_stuff;
280    int id;
281
282    /* Do real locking of the user database */
283    for (i = 0; i < 10; i++)
284      if (setuserdb(S_WRITE) == 0) {
285        fd = 1;
286        break;
287      }
288      else
289        sleep(1);
290
291    if (fd != 1)
292      {
293        sprintf(passerr, "Warning: Couldn't put you in the password file; error %d from setuserdb");
294        return(passerr);
295      }
296
297/* Need to have these to create empty stanzas, in the */
298/* /etc/security/{environ, limits, user} files so that they pick up */
299/* the default values */
300    putuserattr(p->pw_name,(char *)NULL,((void *) 0),SEC_NEW);
301    putuserattr(p->pw_name,S_ID,p->pw_uid,SEC_INT);
302    putuserattr(p->pw_name,S_PWD,"!",SEC_CHAR);
303    putuserattr(p->pw_name,S_PGRP,"mit",SEC_CHAR);
304    putuserattr(p->pw_name,S_HOME,p->pw_dir,SEC_CHAR);
305    putuserattr(p->pw_name,S_SHELL,p->pw_shell,SEC_CHAR);
306    putuserattr(p->pw_name,S_GECOS,p->pw_gecos,SEC_CHAR);
307    putuserattr(p->pw_name,S_LOGINCHK,1,SEC_BOOL);
308    putuserattr(p->pw_name,S_SUCHK,1,SEC_BOOL);
309    putuserattr(p->pw_name,S_RLOGINCHK,1,SEC_BOOL);
310    putuserattr(p->pw_name,S_ADMIN,0,SEC_BOOL);
311    putuserattr(p->pw_name,(char *)NULL,((void *) 0),SEC_COMMIT);
312    enduserdb();
313
314/* Now, lock the shadow password file */
315    fd = -1;
316    for (i = 0; i < 10; i++)
317      if (setpwdb(S_WRITE) == 0) {
318        fd = 1;
319        break;
320      }
321      else
322        sleep(1);
323
324    if (fd != 1)
325      {
326        sprintf(passerr, "Warning: Couldn't put you in the password file; error %d from setpwdb");
327        return(passerr);
328      }
329
330    strncpy(pw_stuff.upw_name,p->pw_name,PW_NAMELEN);
331    pw_stuff.upw_passwd = p->pw_passwd;
332    pw_stuff.upw_flags = 0;
333    pw_stuff.upw_lastupdate = 0;
334    putuserpw(&pw_stuff);
335    endpwdb();
336#else   /* RIOS */
337#ifndef SOLARIS
338    for (i = 0; i < 10; i++)
339      if ((fd = open("/etc/ptmp", O_RDWR | O_CREAT | O_EXCL, 0644)) == -1 &&
340          errno == EEXIST)
341        sleep(1);
342      else
343        break;
344    if (fd == -1) {
345        if (i < 10)
346          sprintf(passerr, "Warning: Couldn't put you in the password file; error %d locking", errno);
347        else
348          sprintf(passerr, "Warning: Couldn't put you in the password file; couldn't lock", errno);
349        return(passerr);
350    }
351
352    etc_passwd = fopen("/etc/passwd", "a");
353    if (etc_passwd == NULL) {
354        sprintf(passerr, "Warning: Couldn't put you in the password file; error %d in open", ferror(etc_passwd));
355        (void) close(fd);
356        (void) unlink("/etc/ptmp");
357        return(passerr);
358    }
359    fprintf(etc_passwd, "%s:%s:%d:%d:%s:%s:%s\n",
360            p->pw_name,
361            file_exists(NOCRACK) ? "*" : p->pw_passwd,
362            p->pw_uid,
363            p->pw_gid,
364            p->pw_gecos,
365            p->pw_dir,
366            p->pw_shell);
367    (void) fclose(etc_passwd);
368    (void) close(fd);
369    (void) unlink("/etc/ptmp");
370#else
371    long lastchg = DAY_NOW;
372
373/* lock the passwd and the shadow file */
374    if (lckpwdf()) {
375       sprintf(passerr, "Warning: Couldn't put you in the password-shadow file;\
376           couldn't lock", errno);
377        return(passerr);
378    }
379    etc_passwd = fopen("/etc/passwd", "a");
380    if (etc_passwd == NULL) {
381        sprintf(passerr, "Warning: Couldn't put you in the password file; error %d in open", ferror(etc_passwd));
382        (void)ulckpwdf();
383        return(passerr);
384    }
385    etc_shadow = fopen("/etc/shadow", "a");
386    if (etc_shadow == NULL) {
387        sprintf(passerr, "Warning: Couldn't put you in the shadow file; error %d in open", ferror(etc_shadow));
388        (void)ulckpwdf();
389        return(passerr);
390    }
391    fprintf(etc_shadow,"%s:%s:%d::::::\n",
392            p->pw_name,
393            p->pw_passwd,
394            lastchg);
395    (void) fclose(etc_shadow);
396    fprintf(etc_passwd, "%s:%s:%d:%d:%s:%s:%s\n",
397            p->pw_name,
398            "x",
399            p->pw_uid,
400            p->pw_gid,
401            p->pw_gecos,
402            p->pw_dir,
403            p->pw_shell);
404    (void) fclose(etc_passwd);
405    (void) ulckpwdf();
406#endif /* SOLARIS */
407#endif  /* RIOS */
408
409    return(NULL);
410}
411
412char *athena_authenticate(user, passwd)
413     char *user, *passwd;
414{
415  int local_ok = 0;
416  struct passwd *pwd;
417  char tkt_file[128];
418  long salt;
419  char saltc[2], c;
420  char encrypt[PASSWORD_LEN+1];
421  int child, error, i;
422  char *errstring = NULL;
423  static char errbuf[1024];
424#if !defined(_AUX_SOURCE) && !defined(SOLARIS)
425  union wait status;
426#else
427  int status;
428#endif
429#ifdef POSIX
430  struct sigaction act;
431#endif
432  athena_login = LOGIN_NONE;
433
434  pwd = athena_getpwnam(user);
435
436  if (!local_passwd)
437    {
438      /* save encrypted password to put in local password file */
439      salt = 9 * getpid();
440      saltc[0] = salt & 077;
441      saltc[1] = (salt>>6) & 077;
442      for (i=0;i<2;i++) {
443        c = saltc[i] + '.';
444        if (c > '9')
445          c += 7;
446        if (c > 'Z')
447          c += 6;
448        saltc[i] = c;
449      }
450      strcpy(encrypt,crypt(passwd, saltc));     
451
452      pwd->pw_passwd = encrypt;
453    }
454
455  if (local_passwd &&
456      !strcmp(crypt(passwd, pwd->pw_passwd), pwd->pw_passwd))
457    local_ok = 1;
458
459  sprintf(tkt_file, "/tmp/tkt_%s.%d", pwd->pw_name, getpid());
460  setenv("KRBTKFILE", tkt_file, 1);
461  /* we set the ticket file here because a previous dest_tkt() might
462     have cached the wrong ticket file. */
463  krb_set_tkt_string(tkt_file);
464
465  if (!(child = fork()))
466    {
467      /* set real uid/gid for kerberos library */
468#ifdef _IBMR2
469      setruid_rios(pwd->pw_uid);
470      setrgid_rios(pwd->pw_gid);
471#else
472#ifdef SOLARIS
473      setuid(pwd->pw_uid);
474      setgid(pwd->pw_gid);
475#else
476      setruid(pwd->pw_uid);
477      setrgid(pwd->pw_gid);
478#endif
479#endif
480      error = get_tickets(user, passwd);
481      memset(passwd, 0, strlen(passwd));
482      _exit(error);
483    }
484
485  if (child == -1)
486    {
487      sprintf(errbuf, "Fork to get tickets failed with error %d", errno);
488      if (local_ok)
489        athena_login = LOGIN_LOCAL;
490        memset(passwd, 0, strlen(passwd));
491        return errbuf;
492    }
493
494#if defined(_IBMR2) || defined(SOLARIS)
495#ifdef POSIX
496  sigemptyset(&act.sa_mask);
497  act.sa_flags = 0;
498  act.sa_handler= (void (*)()) SIG_DFL;
499  (void) sigaction (SIGCHLD, &act, NULL);
500#else
501  signal(SIGCHLD, SIG_DFL);
502#endif
503  (void)waitpid(child, &status, 0);
504#ifdef POSIX
505  act.sa_handler= (void (*)()) SIG_IGN;
506  (void) sigaction (SIGCHLD, &act, NULL);
507#else
508  signal(SIGCHLD, SIG_IGN);
509#endif
510#else
511  (void)waitpid(child, &status, 0);
512#endif
513  memset(passwd, 0, strlen(passwd));
514
515#ifdef POSIX
516  if (!WIFEXITED(status))
517    errstring = "ticket child failed";
518  else
519#endif /* POSIX */
520    { /* this is probably screwed up XXX */
521      error = WEXITSTATUS(status);     
522
523      switch (error) {
524      case KSUCCESS:
525#ifdef SETPAG
526        setpag();
527#endif
528        break;
529      case INTK_BADPW:
530        errstring =  "Incorrect Kerberos password entered.";
531        break;
532      case KDC_PR_UNKNOWN:
533        errstring = "Unknown Kerberos username entered.";
534        break;
535      default:
536        sprintf(errbuf, "Authentication failed: %d: %s.",
537                error, krb_err_txt[error]);
538        errstring = errbuf;
539        break;
540      }
541    }
542
543  if (errstring != NULL && !local_ok)
544    return errstring;
545
546  if (errstring != NULL && local_ok)
547    {
548      athena_login = LOGIN_LOCAL;
549      return errstring;
550    }
551
552  athena_login = LOGIN_KERBEROS;
553  if (!local_passwd)
554    return(add_to_passwd(pwd));
555  else
556    return(NULL);
557}
558
559char *athena_attach(pw, dir, auth)
560     struct passwd *pw;
561     char *dir;
562     int auth;
563{
564  int attach_error, child;
565  int v, out, err;
566#if !defined(_AUX_SOURCE) && !defined(SOLARIS)
567  union wait status;
568#else
569  int status;
570#endif
571#ifdef POSIX
572  struct sigaction act;
573#endif
574  if (!(child = fork()))
575    {
576#if defined(_AIX) || defined (SOLARIS)
577      setuid(pw->pw_uid);
578      setgid(pw->pw_gid);
579#else
580      setruid(pw->pw_uid);
581      setrgid(pw->pw_gid);
582#endif
583
584      out = fileno(stdout);
585      err = fileno(stderr);
586
587      v = open("/dev/null", O_WRONLY);
588      dup2(v, out);
589      dup2(v, err);
590      close(v);
591
592      execl(ATTACH, "attach", "-nozephyr", auth ? "-y" : "-n", dir, 0);
593      _exit(255); /* Attach isn't supposed to return 255 */
594    }
595
596  if (child == -1)
597    {
598      sprintf(att_errbuf, "Fork for attach failed with error %d", errno);
599      return att_errbuf;
600    }
601
602#if defined(_IBMR2) || defined(SOLARIS)
603#ifdef POSIX
604  sigemptyset(&act.sa_mask);
605  act.sa_flags = 0;
606  act.sa_handler= (void (*)()) SIG_DFL;
607  (void) sigaction (SIGCHLD, &act, NULL);
608#else
609  signal(SIGCHLD, SIG_DFL);
610#endif
611  (void)waitpid(child, &status, 0);
612#ifdef POSIX
613  act.sa_handler= (void (*)()) SIG_IGN;
614  (void) sigaction (SIGCHLD, &act, NULL);
615#else
616  signal(SIGCHLD, SIG_IGN);
617#endif
618#else
619  (void)waitpid(child, &status, 0);
620#endif
621
622#ifdef POSIX
623  if (!WIFEXITED(status))
624    {
625      sprintf(att_errbuf, "Bad exit on attach child");
626      return att_errbuf;
627    }
628  else
629#endif /* POSIX */
630    { /* this is probably screwed up XXX */
631      attach_error = WEXITSTATUS(status);     
632
633      if (attach_error)
634        {
635          switch(attach_error)
636            {
637            case 255:
638              sprintf(att_errbuf, "Couldn't exec attach");
639              break;
640            case 11:
641              sprintf(att_errbuf, "Server not responding");
642              break;
643            case 12:
644              sprintf(att_errbuf, "Authentication failure");
645              break;
646            case 20:
647              sprintf(att_errbuf, "Filesystem does not exist");
648              break;
649            case 24:
650              sprintf(att_errbuf, "You are not allowed to attach this filesystem.");
651              break;
652            case 25:
653              sprintf(att_errbuf, "You are not allowed to attach a filesystem here.");
654              break;
655            default:
656              sprintf(att_errbuf, "Could not attach directory: attach returned error %d", attach_error);
657              break;
658            }
659          return att_errbuf;
660        }
661    }
662  return NULL;
663}
664
665char *athena_attachhomedir(pw, auth)
666     struct passwd *pw;
667     int auth;
668{
669  /* Delete empty directory if it exists.  We just try to rmdir the
670   * directory, and if it's not empty that will fail.
671   */
672  rmdir(pw->pw_dir);
673
674  /* If a good local homedir exists, use it */
675  if (file_exists(pw->pw_dir) && !IsRemoteDir(pw->pw_dir) &&
676      homedirOK(pw->pw_dir))
677    return(NULL);
678
679  /* Using homedir already there that may or may not be good. */
680  if (file_exists(NOATTACH) && file_exists(pw->pw_dir) &&
681      homedirOK(pw->pw_dir)) {
682    return(NULL);
683  }
684
685  if (file_exists(NOATTACH))
686    {
687      sprintf(att_errbuf, "This workstation is configured not to create local home directories.");
688      return att_errbuf;
689    }
690
691  return athena_attach(pw, pw->pw_name, auth);
692}
693
694IsRemoteDir(dir)
695char *dir;
696{
697#ifdef _AIX
698#define REMOTEDONE
699    struct stat stbuf;
700
701    if (statx(dir, &stbuf, 0, STX_NORMAL))
702        return(TRUE);
703    return((stbuf.st_flag & FS_REMOTE) ? TRUE : FALSE);
704#endif
705
706#ifdef ultrix
707#define REMOTEDONE
708    struct fs_data sbuf;
709
710    if (statfs(dir, &sbuf) < 0)
711        return(TRUE);
712
713    switch(sbuf.fd_req.fstype) {
714    case GT_ULTRIX:
715    case GT_CDFS:
716        return(FALSE);
717    }
718    return(TRUE);
719#endif
720
721#if (defined(vax) || defined(ibm032) || defined(sun)) && !defined(REMOTEDONE)
722#define REMOTEDONE
723#if defined(vax) || defined(ibm032)
724#define NFS_MAJOR 0xff
725#endif
726#if defined(sun)
727#define NFS_MAJOR 130
728#endif
729    struct stat stbuf;
730
731    if (stat(dir, &stbuf))
732        return(TRUE);
733
734    if (major(stbuf.st_dev) == NFS_MAJOR)
735        return(TRUE);
736    if (stbuf.st_dev == 0x0001)                 /* AFS */
737        return(TRUE);
738
739    return(FALSE);
740#endif
741
742#ifndef REMOTEDONE
743    ERROR --- ROUTINE NOT IMPLEMENTED ON THIS PLATFORM;
744#endif
745}
746
747/* Function Name: homedirOK
748 * Description: checks to see if our homedir is okay, i.e. exists and
749 *      contains at least 1 file
750 * Arguments: dir - the directory to check.
751 * Returns: TRUE if the homedir is okay.
752 */
753
754int homedirOK(dir)
755char *dir;
756{
757    DIR *dp;
758#ifdef POSIX
759    struct dirent *temp;
760#else
761    struct direct *temp;
762#endif
763    int count;
764
765    if ((dp = opendir(dir)) == NULL)
766      return(FALSE);
767
768    /* Make sure that there is something here besides . and .. */
769    for (count = 0; count < 3 ; count++)
770      temp = readdir(dp);
771
772    closedir(dp);
773    return(temp != NULL);
774}
775
776fork_dest_tkt(pw)
777     struct passwd *pw;
778{
779  int child, status;
780#ifdef POSIX
781  struct sigaction act;
782#endif
783  if (!(child = fork()))
784    {
785      /* set real uid/gid for kerberos library */
786#ifdef _IBMR2
787      setruid_rios(pw->pw_uid);
788      setrgid_rios(pw->pw_gid);
789#else
790#ifdef SOLARIS
791      setuid(pw->pw_uid);
792      setgid(pw->pw_gid);
793#else
794      setruid(pw->pw_uid);
795      setrgid(pw->pw_gid);
796#endif
797#endif
798
799      dest_tkt();
800      _exit(0);
801    }
802
803  if (child == -1)
804    {
805/*      sprintf(errbuf, "Fork to get tickets failed with error %d", errno);
806      if (local_ok)
807        athena_login = LOGIN_LOCAL;
808      memset(passwd, 0, strlen(passwd));
809      return errbuf;*/
810      return;
811    }
812
813#if defined(_IBMR2) || defined(SOLARIS)
814#ifdef POSIX
815  sigemptyset(&act.sa_mask);
816  act.sa_flags = 0;
817  act.sa_handler= (void (*)()) SIG_DFL;
818  (void) sigaction (SIGCHLD, &act, NULL);
819#else
820  signal(SIGCHLD, SIG_DFL);
821#endif
822  (void)waitpid(child, &status, 0);
823#ifdef POSIX
824  act.sa_handler= (void (*)()) SIG_IGN;
825  (void) sigaction (SIGCHLD, &act, NULL);
826#else
827  signal(SIGCHLD, SIG_IGN);
828#endif
829#else
830  (void)waitpid(child, &status, 0);
831#endif
832}
833
834/*
835 * Should be called when root
836 */
837athena_logout(pw)
838     struct passwd *pw;
839{
840  FILE *att, *unlog;
841  int detach_error, unlog_error, pid;
842  char str_uid[10];
843  if (athena_login != LOGIN_NONE)
844    {
845      /* destroy kerberos tickets */
846      if (athena_login == LOGIN_KERBEROS)
847        {
848#ifdef _IBMR2
849          fork_dest_tkt(pw);
850#else
851          dest_tkt();
852#endif
853#ifdef SETPAG
854          ktc_ForgetAllTokens();
855#endif
856          if ((pid = fork()) == 0)
857            {
858              execl(FSID, FSID, "-q", "-u", "-f", pw->pw_name, 0);
859              exit(1);
860            }
861        }
862      athena_login = LOGIN_NONE;
863#ifdef SOLARIS
864      /* lock before */
865      if (lckpwdf()) return;
866
867      remove_from_passwd(pw);
868      remove_from_shadow(pw);
869#endif
870#ifdef oldcode
871      if (!user_logged_in(pw->pw_name))
872        {
873          chdir("/");
874          sprintf(str_uid, "#%d", pw->pw_uid);
875
876          if ((pid = fork()) == 0) /* we just don't care about failure... */
877            {
878              execl(DETACH, DETACH, "-quiet", "-user", str_uid, "-a", 0);
879              exit(1);
880            }
881
882          if (pid != -1)
883            if ((pid = fork()) == 0)
884              {
885                execl(UNLOG, UNLOG, 0);
886                exit(1);
887              }
888        }
889#endif
890    }
891}
892
893#if defined(_AIX) && defined(_IBMR2)
894#include <sys/id.h>
895
896/*
897 * AIX 3.1 has bizzarre ideas about changing uids and gids around.  They are
898 * such that the sete{u,g}id and setr{u,g}id calls here fail.  For this reason
899 * we are replacing the sete{u,g}id and setr{u,g}id calls.
900 *
901 * The bizzarre ideas are as follows:
902 *
903 * The effective ID may be changed only to the current real or
904 * saved IDs.
905 *
906 * The saved uid may be set only if the real and effective
907 * uids are being set to the same value.
908 *
909 * The real uid may be set only if the effective
910 * uid is being set to the same value.
911 *
912 * Yes, POSIX rears its head..
913 */
914
915#ifdef __STDC__
916int setruid_rios(uid_t ruid)
917#else
918int setruid_rios(ruid)
919  uid_t ruid;
920#endif /* __STDC__ */
921{
922    uid_t euid;
923
924    if (ruid == -1)
925        return (0);
926
927    euid = geteuid();
928
929    if (setuidx(ID_REAL | ID_EFFECTIVE, ruid) == -1)
930        return (-1);
931   
932    return (setuidx(ID_EFFECTIVE, euid));
933}
934
935
936#ifdef __STDC__
937int seteuid_rios(uid_t euid)
938#else
939int seteuid_rios(euid)
940  uid_t euid;
941#endif /* __STDC__ */
942{
943    uid_t ruid;
944
945    if (euid == -1)
946        return (0);
947
948    ruid = getuid();
949
950    if (setuidx(ID_SAVED | ID_REAL | ID_EFFECTIVE, euid) == -1)
951        return (-1);
952   
953    return (setruid_rios(ruid));
954}
955
956
957#ifdef __STDC__
958int setreuid_rios(uid_t ruid, uid_t euid)
959#else
960int setreuid_rios(ruid, euid)
961  uid_t ruid;
962  uid_t euid;
963#endif /* __STDC__ */
964{
965    if (seteuid_rios(euid) == -1)
966        return (-1);
967
968    return (setruid_rios(ruid));
969}
970
971#ifdef __STDC__
972int setuid_rios(uid_t uid)
973#else
974int setuid_rios(uid)
975  uid_t uid;
976#endif /* __STDC__ */
977{
978    return (setreuid_rios(uid, uid));
979}
980
981#ifdef __STDC__
982int setrgid_rios(gid_t rgid)
983#else
984int setrgid_rios(rgid)
985  gid_t rgid;
986#endif /* __STDC__ */
987{
988    gid_t egid;
989
990    if (rgid == -1)
991        return (0);
992
993    egid = getegid();
994
995    if (setgidx(ID_REAL | ID_EFFECTIVE, rgid) == -1)
996        return (-1);
997   
998    return (setgidx(ID_EFFECTIVE, egid));
999}
1000
1001
1002#ifdef __STDC__
1003int setegid_rios(gid_t egid)
1004#else
1005int setegid_rios(egid)
1006  gid_t egid;
1007#endif /* __STDC__ */
1008{
1009    gid_t rgid;
1010
1011    if (egid == -1)
1012        return (0);
1013
1014    rgid = getgid();
1015
1016    if (setgidx(ID_SAVED | ID_REAL | ID_EFFECTIVE, egid) == -1)
1017        return (-1);
1018   
1019    return (setrgid_rios(rgid));
1020}
1021
1022
1023#ifdef __STDC__
1024int setregid_rios(gid_t rgid, gid_t egid)
1025#else
1026int setregid_rios(rgid, egid)
1027  gid_t rgid;
1028  gid_t egid;
1029#endif /* __STDC__ */
1030{
1031    if (setegid_rios(egid) == -1)
1032        return (-1);
1033
1034    return (setrgid_rios(rgid));
1035}
1036
1037#ifdef __STDC__
1038int setgid_rios(gid_t gid)
1039#else
1040int setgid_rios(gid)
1041  gid_t gid;
1042#endif /* __STDC__ */
1043{
1044    return (setregid_rios(gid, gid));
1045}
1046
1047#endif /* RIOS */
1048#endif
Note: See TracBrowser for help on using the repository browser.