]> arthur.barton.de Git - netatalk.git/blob - etc/uams/uams_passwd.c
pap: Allow login using gecos name too, fix most obvious buffers overrun... from
[netatalk.git] / etc / uams / uams_passwd.c
1 /*
2  * $Id: uams_passwd.c,v 1.20 2003-05-14 15:13:50 didg Exp $
3  *
4  * Copyright (c) 1990,1993 Regents of The University of Michigan.
5  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) 
6  * All Rights Reserved.  See COPYRIGHT.
7  */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif /* HAVE_CONFIG_H */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15
16 /* STDC check */
17 #if STDC_HEADERS
18 #include <string.h>
19 #else /* STDC_HEADERS */
20 #ifndef HAVE_STRCHR
21 #define strchr index
22 #define strrchr index
23 #endif /* HAVE_STRCHR */
24 char *strchr (), *strrchr ();
25 #ifndef HAVE_MEMCPY
26 #define memcpy(d,s,n) bcopy ((s), (d), (n))
27 #define memmove(d,s,n) bcopy ((s), (d), (n))
28 #endif /* ! HAVE_MEMCPY */
29 #endif /* STDC_HEADERS */
30
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif /* HAVE_UNISTD_H */
34 #ifndef NO_CRYPT_H
35 #include <crypt.h>
36 #endif /* ! NO_CRYPT_H */
37 #include <pwd.h>
38 #include <atalk/logger.h>
39
40 #ifdef SOLARIS
41 #define SHADOWPW
42 #endif /* SOLARIS */
43
44 #ifdef SHADOWPW
45 #include <shadow.h>
46 #endif /* SHADOWPW */
47
48 #include <atalk/afp.h>
49 #include <atalk/uam.h>
50
51 #define PASSWDLEN 8
52
53 #ifndef MIN
54 #define MIN(a,b) ((a) < (b) ? (a) : (b))
55 #endif /* MIN */
56
57
58 #ifdef TRU64
59 #include <sia.h>
60 #include <siad.h>
61
62 static char *clientname;
63 #endif /* TRU64 */
64
65 static int pwd_login(void *obj, char *username, int ulen, struct passwd **uam_pwd,
66                         char *ibuf, int ibuflen,
67                         char *rbuf, int *rbuflen)
68 {
69     char  *p;
70     struct passwd *pwd;
71 #ifdef SHADOWPW
72     struct spwd *sp;
73 #endif /* SHADOWPW */
74
75 #ifdef TRU64
76     if( uam_afpserver_option( obj, UAM_OPTION_CLIENTNAME,
77                               (void *) &clientname, NULL ) < 0 )
78         return AFPERR_MISC;
79 #endif /* TRU64 */
80
81     if (ibuflen < PASSWDLEN) {
82         return( AFPERR_PARAM );
83     }
84     ibuf[ PASSWDLEN ] = '\0';
85
86     if (( pwd = uam_getname(username, ulen)) == NULL ) {
87         return AFPERR_PARAM;
88     }
89
90     LOG(log_info, logtype_uams, "cleartext login: %s", username);
91
92     if (uam_checkuser(pwd) < 0) {
93         LOG(log_info, logtype_uams, "not a valid user");
94         return AFPERR_NOTAUTH;
95     }
96
97 #ifdef SHADOWPW
98     if (( sp = getspnam( pwd->pw_name )) == NULL ) {
99         LOG(log_info, logtype_uams, "no shadow passwd entry for %s", username);
100         return AFPERR_NOTAUTH;
101     }
102     pwd->pw_passwd = sp->sp_pwdp;
103 #endif /* SHADOWPW */
104
105     if (!pwd->pw_passwd) {
106         return AFPERR_NOTAUTH;
107     }
108
109     *uam_pwd = pwd;
110
111 #ifdef TRU64
112     {
113         int ac;
114         char **av;
115         char hostname[256];
116
117         uam_afp_getcmdline( &ac, &av );
118         sprintf( hostname, "%s@%s", username, clientname );
119
120         if( uam_sia_validate_user( NULL, ac, av, hostname, username,
121                                    NULL, FALSE, NULL, ibuf ) != SIASUCCESS )
122             return AFPERR_NOTAUTH;
123
124         return AFP_OK;
125     }
126 #else /* TRU64 */
127     p = crypt( ibuf, pwd->pw_passwd );
128     if ( strcmp( p, pwd->pw_passwd ) == 0 )
129         return AFP_OK;
130 #endif /* TRU64 */
131
132     return AFPERR_NOTAUTH;
133
134 }
135
136 /* cleartxt login */
137 static int passwd_login(void *obj, struct passwd **uam_pwd,
138                         char *ibuf, int ibuflen,
139                         char *rbuf, int *rbuflen)
140 {
141     char *username;
142     int len, ulen;
143
144     *rbuflen = 0;
145
146     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME,
147                              (void *) &username, &ulen) < 0)
148         return AFPERR_MISC;
149
150     if (ibuflen <= 1) {
151         return( AFPERR_PARAM );
152     }
153
154     len = (unsigned char) *ibuf++;
155     ibuflen--;
156     if (!len || len > ibuflen || len > ulen ) {
157         return( AFPERR_PARAM );
158     }
159     memcpy(username, ibuf, len );
160     ibuf += len;
161     ibuflen -=len;
162     username[ len ] = '\0';
163
164     if ((unsigned long) ibuf & 1) { /* pad character */
165         ++ibuf;
166         ibuflen--;
167     }
168     return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen));
169     
170 }
171
172 /* cleartxt login ext 
173  * uname format :
174     byte      3
175     2 bytes   len (network order)
176     len bytes unicode name
177 */
178 static int passwd_login_ext(void *obj, char *uname, struct passwd **uam_pwd,
179                         char *ibuf, int ibuflen,
180                         char *rbuf, int *rbuflen)
181 {
182     char       *username;
183     int        len, ulen;
184     u_int16_t  temp16;
185
186     *rbuflen = 0;
187
188     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME,
189                              (void *) &username, &ulen) < 0)
190         return AFPERR_MISC;
191
192     if (*uname != 3)
193         return AFPERR_PARAM;
194     uname++;
195     memcpy(&temp16, uname, sizeof(temp16));
196     len = ntohs(temp16);
197     if (!len || len > ulen ) {
198         return( AFPERR_PARAM );
199     }
200     memcpy(username, uname +2, len );
201     username[ len ] = '\0';
202     return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen));
203 }
204                         
205
206 #if 0
207 /* change passwd */
208 static int passwd_changepw(void *obj, char *username,
209                            struct passwd *pwd, char *ibuf,
210                            int ibuflen, char *rbuf, int *rbuflen)
211 {
212 #ifdef SHADOWPW
213     struct spwd *sp;
214 #endif /* SHADOWPW */
215     char pw[PASSWDLEN + 1], *p;
216     uid_t uid = geteuid();
217
218     if (uam_checkuser(pwd) < 0)
219         return AFPERR_ACCESS;
220
221     /* old password */
222     memcpy(pw, ibuf, PASSWDLEN);
223     memset(ibuf, 0, PASSWDLEN);
224     pw[PASSWDLEN] = '\0';
225
226 #ifdef SHADOWPW
227     if (( sp = getspnam( pwd->pw_name )) == NULL ) {
228         LOG(log_info, logtype_uams, "no shadow passwd entry for %s", username);
229         return AFPERR_PARAM;
230     }
231     pwd->pw_passwd = sp->sp_pwdp;
232 #endif /* SHADOWPW */
233
234     p = crypt(pw, pwd->pw_passwd );
235     if (strcmp( p, pwd->pw_passwd )) {
236         memset(pw, 0, sizeof(pw));
237         return AFPERR_NOTAUTH;
238     }
239
240     /* new password */
241     ibuf += PASSWDLEN;
242     ibuf[PASSWDLEN] = '\0';
243
244 #ifdef SHADOWPW
245 #else /* SHADOWPW */
246 #endif /* SHADOWPW */
247     return AFP_OK;
248 }
249 #endif /* 0 */
250
251
252 /* Printer ClearTxtUAM login */
253 static int passwd_printer(start, stop, username, out)
254 char    *start, *stop, *username;
255 struct papfile  *out;
256 {
257     struct passwd *pwd;
258 #ifdef SHADOWPW
259     struct spwd *sp;
260 #endif /* SHADOWPW */
261     char *data, *p, *q;
262     char        password[PASSWDLEN + 1] = "\0";
263     static const char *loginok = "0\r";
264     int ulen;
265
266     data = (char *)malloc(stop - start + 2);
267     if (!data) {
268         LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: malloc");
269         return(-1);
270     }
271     strncpy(data, start, stop - start + 1);
272     data[stop - start + 2] = 0;
273
274     /* We are looking for the following format in data:
275      * (username) (password)
276      *
277      * Let's hope username doesn't contain ") ("!
278      */
279
280     /* Parse input for username in () */
281     if ((p = strchr(data, '(' )) == NULL) {
282         LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: username not found in string");
283         free(data);
284         return(-1);
285     }
286     p++;
287     if ((q = strstr(data, ") (" )) == NULL) {
288         LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: username not found in string");
289         free(data);
290         return(-1);
291     }
292     strncpy(username, p, MIN( UAM_USERNAMELEN, (q - p)) );
293     username[ UAM_USERNAMELEN+1] = '\0';
294
295
296     /* Parse input for password in next () */
297     p = q + 3;
298     if ((q = strrchr(data, ')' )) == NULL) {
299         LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: password not found in string");
300         free(data);
301         return(-1);
302     }
303     strncpy(password, p, MIN(PASSWDLEN, q - p) );
304     password[ PASSWDLEN+1] = '\0';
305
306
307     /* Done copying username and password, clean up */
308     free(data);
309
310     ulen = strlen(username);
311
312     if (( pwd = uam_getname(username, ulen)) == NULL ) {
313         LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: ( %s ) not found ",
314             username);
315         return(-1);
316     }
317
318     if (uam_checkuser(pwd) < 0) {
319         /* syslog of error happens in uam_checkuser */
320         return(-1);
321     }
322
323 #ifdef SHADOWPW
324     if (( sp = getspnam( pwd->pw_name )) == NULL ) {
325         LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: no shadow passwd entry for %s",
326             username);
327         return(-1);
328     }
329     pwd->pw_passwd = sp->sp_pwdp;
330 #endif /* SHADOWPW */
331
332     if (!pwd->pw_passwd) {
333         LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: no password for %s",
334             username);
335         return(-1);
336     }
337
338 #ifdef AFS
339     if ( kcheckuser( pwd, password) == 0)
340         return(0);
341 #endif /* AFS */
342
343     p = crypt(password, pwd->pw_passwd);
344     if (strcmp(p, pwd->pw_passwd) != 0) {
345         LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: %s: bad password", username);
346         return(-1);
347     }
348
349     /* Login successful */
350     append(out, loginok, strlen(loginok));
351     LOG(log_info, logtype_uams, "Login ClearTxtUAM: %s", username);
352     return(0);
353 }
354
355 #ifdef ATACC
356 int uam_setup(const char *path)
357 {
358     if (uam_register_fn(UAM_SERVER_LOGIN_EXT, path, "Cleartxt Passwrd",
359                      passwd_login, NULL, NULL, passwd_login_ext) < 0)
360         return -1;
361     if (uam_register_fn(UAM_SERVER_PRINTAUTH, path, "ClearTxtUAM",
362                      passwd_printer) < 0)
363         return -1;
364
365     return 0;
366 }
367 #else 
368 static int uam_setup(const char *path)
369 {
370     if (uam_register(UAM_SERVER_LOGIN_EXT, path, "Cleartxt Passwrd",
371                      passwd_login, NULL, NULL, passwd_login_ext) < 0)
372         return -1;
373     if (uam_register(UAM_SERVER_PRINTAUTH, path, "ClearTxtUAM",
374                      passwd_printer) < 0)
375         return -1;
376
377     return 0;
378 }
379
380 #endif
381
382 static void uam_cleanup(void)
383 {
384     uam_unregister(UAM_SERVER_LOGIN, "Cleartxt Passwrd");
385     uam_unregister(UAM_SERVER_PRINTAUTH, "ClearTxtUAM");
386 }
387
388 UAM_MODULE_EXPORT struct uam_export uams_clrtxt = {
389             UAM_MODULE_SERVER,
390             UAM_MODULE_VERSION,
391             uam_setup, uam_cleanup
392         };