Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / support / pop / popauth.c
1 /* popauth.c - manipulate POP authorization DB */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: popauth.c,v 1.7 1992/12/15 00:20:22 jromine Exp $";
4 #endif  /* lint */
5
6 #include "../h/mh.h"
7 #include "popauth.h"
8 #undef  DBM             /* used by mts.c and ndbm.h */
9 #include <ndbm.h>
10 #include <pwd.h>
11 #include <stdio.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <sys/file.h>
15 #ifdef  SYS5
16 #include <fcntl.h>
17 #endif
18 #include "../zotnet/bboards.h"
19 #include "../zotnet/mts.h"
20
21 /* \f */
22
23 static struct swit switches[] = {
24 #define INITSW  0
25     "init", 0,
26 #define LISTSW  1
27     "list", 0,
28 #define USERSW  2
29     "user name", 0,
30
31 #define HELPSW  3
32     "help", 4,
33
34     NULL, 0
35 };
36
37 /* \f */
38
39 char   *getpass ();
40
41 /* \f */
42
43 /* ARGSUSED */
44
45 main (argc, argv)
46 int     argc;
47 char   *argv[];
48 {
49     int     flags,
50             i,
51             initsw = 0,
52             insist,
53             listsw = 0;
54     long    clock;
55     char   *bp,
56            *cp,
57            *usersw = NULL,
58             buf[100],
59           **ap,
60           **argp,
61            *arguments[MAXARGS];
62     datum   key,
63             value;
64     DBM    *db;
65     struct authinfo auth;
66
67     invo_name = r1bindex (argv[0], '/');
68     m_foil (NULLCP);
69     if ((cp = m_find (invo_name)) != NULL) {
70         ap = brkstring (cp = getcpy (cp), " ", "\n");
71         ap = copyip (ap, arguments);
72     }
73     else
74         ap = arguments;
75     (void) copyip (argv + 1, ap);
76     argp = arguments;
77
78 /* \f */
79
80     while (cp = *argp++) {
81         if (*cp == '-')
82             switch (smatch (++cp, switches)) {
83                 case AMBIGSW: 
84                     ambigsw (cp, switches);
85                     done (1);
86                 case UNKWNSW: 
87                     adios (NULLCP, "-%s unknown", cp);
88                 case HELPSW: 
89                     (void) sprintf (buf, "%s [switches]", invo_name);
90                     help (buf, switches);
91                     done (1);
92
93                 case INITSW:
94                     initsw = 1, listsw = 0;
95                     continue;
96                 case LISTSW:
97                     listsw = 1, initsw = 0;
98                     continue;
99                 case USERSW:
100                     if (!(usersw = *argp++) || *usersw == '-')
101                         adios (NULLCP, "missing argument to %s", argp[-2]);
102                     continue;
103             }
104         adios (NULLCP, "usage: %s [switches]", invo_name);
105     }
106
107 /* \f */
108
109 #ifndef APOP
110     adios (NULLCP, "not compiled with APOP option");
111 #else
112     if (getuid ())
113         initsw = listsw = 0, usersw = NULL;
114
115     if (initsw) {
116         struct passwd *pw;
117         struct stat st;
118
119         if ((pw = getpwnam (POPUID)) == NULL)
120             adios (NULLCP, "POP user-id unknown");
121
122         (void) sprintf (buf, "%s.dir", APOP);
123         if (stat (buf, &st) != NOTOK) {
124             if (!getanswer ("Really initialize POP authorization DB? "))
125                 done (1);
126             (void) unlink (buf);
127             (void) sprintf (buf, "%s.pag", APOP);           
128             (void) unlink (buf);
129         }
130         if ((db = dbm_open (APOP, O_RDWR | O_CREAT, 0600)) == NULL)
131             adios (APOP, "unable to create POP authorization DB");
132         if (fchown (dbm_dirfno (db), pw -> pw_uid, pw -> pw_gid) == NOTOK
133                 || fchown (dbm_pagfno (db), pw -> pw_uid, pw -> pw_gid)
134                         == NOTOK)
135             advise (" ", "error setting ownership of POP authorization DB");
136
137         done (0);
138     }
139
140     if ((db = dbm_open (APOP, O_RDONLY, 0)) == NULL)
141         adios (APOP, "unable to open POP authorization DB");
142
143     if (flock (dbm_pagfno (db), LOCK_SH) == NOTOK)
144         adios (APOP, "unable to lock POP authorization DB");
145
146     if (listsw) {
147         if (usersw) {
148             key.dsize = strlen (key.dptr = usersw) + 1;
149             value = dbm_fetch (db, key);
150             if (value.dptr == NULL)
151                 adios (NULLCP, "no such entry in POP authorization DB");
152             bcopy (value.dptr, (char *) &auth, sizeof auth);
153             printf ("%s\n", key.dptr);
154         }
155         else
156             for (key = dbm_firstkey (db); key.dptr; key = dbm_nextkey (db)) {
157                 printf ("%s", key.dptr);
158                 value = dbm_fetch (db, key);
159                 if (value.dptr == NULL)
160                     printf (" - no information?!?\n");
161                 else {
162                     bcopy (value.dptr, (char *) &auth, sizeof auth);
163                     printf ("\n");
164                 }
165             }
166
167         dbm_close (db);
168
169         done (0);
170     }
171
172     if (usersw == NULL)
173         usersw = getusr ();
174
175     fprintf (stderr, "Changing POP password for %s.\n", usersw);
176
177     key.dsize = strlen (key.dptr = usersw) + 1;
178     value = dbm_fetch (db, key);
179     if (value.dptr != NULL) {
180         bcopy (value.dptr, (char *) &auth, sizeof auth);
181         dbm_close (db);
182
183         if ((i = strlen (strcpy (buf, getpass ("Old password:")))) == 0
184                 || auth.auth_secretlen != i
185                 || bcmp (buf, auth.auth_secret, i))
186             fprintf (stderr, "Sorry.\n"), exit (1);
187     }
188     else
189         dbm_close (db);
190
191 #ifdef  lint
192     flags = 0;
193 #endif  /* lint */
194     for (insist = 0; insist < 2; insist++) {
195         int     i;
196         char    c;
197
198         if (insist)
199             printf ("Please use %s.\n",
200                     flags == 1 ? "at least one non-numeric character"
201                     : "a longer password");
202
203         if ((i = strlen (strcpy (buf, getpass ("New password:")))) == 0) {
204             fprintf (stderr, "Password unchanged.\n");
205             exit (1);
206         }
207
208         flags = 0;
209         for (cp = buf; c = *cp++;)
210             if (c >= 'a' && c <= 'z')
211                 flags |= 2;
212             else
213                 if (c >= 'A' && c <= 'Z')
214                     flags |= 4;
215                 else
216                     if (c >= '0' && c <= '9')
217                         flags |= 1;
218                     else
219                         flags |= 8;
220
221         if ((flags >= 7 && i >= 4)
222                 || ((flags == 2 || flags == 4) && i >= 6)
223                 || ((flags == 3 || flags == 5 || flags == 6) && i >= 5))
224             break;
225     }
226
227     if (strcmp (buf, getpass ("Retype new password:"))) {
228         fprintf (stderr, "Mismatch - password unchanged.\n");
229         exit (1);
230     }
231
232     if ((db = dbm_open (APOP, O_RDWR, 0)) == NULL)
233         adios (APOP, "unable to open POP authorization DB");
234
235     if (flock (dbm_pagfno (db), LOCK_EX) == NOTOK)
236         adios (APOP, "unable to lock POP authorization DB");
237
238     key.dsize = strlen (key.dptr = usersw) + 1;
239
240     buf[sizeof auth.auth_secret] = NULL;
241     bcopy (buf, auth.auth_secret, auth.auth_secretlen = strlen (buf));
242     value.dptr = (char *) &auth, value.dsize = sizeof auth;
243
244     if (dbm_store (db, key, value, DBM_REPLACE))
245         adios (NULLCP, "POP authorization DB may be corrupt?!?");
246     dbm_close (db);
247 #endif
248
249     done (0);
250     /* NOTREACHED */
251 }