]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/telnet/libtelnet/sra.c
This commit was generated by cvs2svn to compensate for changes in r85552,
[FreeBSD/FreeBSD.git] / contrib / telnet / libtelnet / sra.c
1 #include <sys/cdefs.h>
2 __FBSDID("$FreeBSD$");
3
4 #ifdef  SRA
5 #include <sys/types.h>
6 #include <arpa/telnet.h>
7 #include <stdio.h>
8 #ifdef  __STDC__
9 #include <stdlib.h>
10 #endif
11 #ifdef  NO_STRING_H
12 #include <strings.h>
13 #else
14 #include <string.h>
15 #endif
16
17 #if !defined(NOPAM)
18 #include <security/pam_appl.h>
19 #else
20 #include <unistd.h>
21 #endif
22
23 #include <pwd.h>
24 #include <syslog.h>
25 #include <ttyent.h>
26
27 #include "auth.h"
28 #include "misc.h"
29 #include "encrypt.h"
30 #include "pk.h"
31
32 char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
33 char *user,*pass,*xuser,*xpass;
34 DesData ck;
35 IdeaData ik;
36
37 extern int auth_debug_mode;
38 extern char *line;
39
40 static int sra_valid = 0;
41 static int passwd_sent = 0;
42
43 static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
44                                         AUTHTYPE_SRA, };
45
46 #define SRA_KEY 0
47 #define SRA_USER 1
48 #define SRA_CONTINUE 2
49 #define SRA_PASS 3
50 #define SRA_ACCEPT 4
51 #define SRA_REJECT 5
52
53 static int check_user(const char *, const char *);
54
55 /* support routine to send out authentication message */
56 static int
57 Data(Authenticator *ap, int type, void *d, int c)
58 {
59         unsigned char *p = str_data + 4;
60         unsigned char *cd = (unsigned char *)d;
61
62         if (c == -1)
63                 c = strlen((char *)cd);
64
65         if (auth_debug_mode) {
66                 printf("%s:%d: [%d] (%d)",
67                         str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
68                         str_data[3],
69                         type, c);
70                 printd(d, c);
71                 printf("\r\n");
72         }
73         *p++ = ap->type;
74         *p++ = ap->way;
75         *p++ = type;
76         while (c-- > 0) {
77                 if ((*p++ = *cd++) == IAC)
78                         *p++ = IAC;
79         }
80         *p++ = IAC;
81         *p++ = SE;
82         if (str_data[3] == TELQUAL_IS)
83                 printsub('>', &str_data[2], p - (&str_data[2]));
84         return(net_write(str_data, p - str_data));
85 }
86
87 int
88 sra_init(Authenticator *ap, int server)
89 {
90         if (server)
91                 str_data[3] = TELQUAL_REPLY;
92         else
93                 str_data[3] = TELQUAL_IS;
94
95         user = (char *)malloc(256);
96         xuser = (char *)malloc(513);
97         pass = (char *)malloc(256);
98         xpass = (char *)malloc(513);
99
100         if (user == NULL || xuser == NULL || pass == NULL || xpass ==
101         NULL)
102                 return 0; /* malloc failed */
103
104         passwd_sent = 0;
105         
106         genkeys(pka,ska);
107         return(1);
108 }
109
110 /* client received a go-ahead for sra */
111 int
112 sra_send(Authenticator *ap)
113 {
114         /* send PKA */
115
116         if (auth_debug_mode)
117                 printf("Sent PKA to server.\r\n" );
118         printf("Trying SRA secure login:\r\n");
119         if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
120                 if (auth_debug_mode)
121                         printf("Not enough room for authentication data\r\n");
122                 return(0);
123         }
124
125         return(1);
126 }
127
128 /* server received an IS -- could be SRA KEY, USER, or PASS */
129 void
130 sra_is(Authenticator *ap, unsigned char *data, int cnt)
131 {
132         int valid;
133         Session_Key skey;
134
135         if (cnt-- < 1)
136                 goto bad;
137         switch (*data++) {
138
139         case SRA_KEY:
140                 if (cnt < HEXKEYBYTES) {
141                         Data(ap, SRA_REJECT, (void *)0, 0);
142                         auth_finished(ap, AUTH_USER);
143                         if (auth_debug_mode) {
144                                 printf("SRA user rejected for bad PKB\r\n");
145                         }
146                         return;
147                 }
148                 if (auth_debug_mode)
149                         printf("Sent pka\r\n");
150                 if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
151                         if (auth_debug_mode)
152                                 printf("Not enough room\r\n");
153                         return;
154                 }
155                 memcpy(pkb,data,HEXKEYBYTES);
156                 pkb[HEXKEYBYTES] = '\0';
157                 common_key(ska,pkb,&ik,&ck);
158                 return;
159
160         case SRA_USER:
161                 /* decode KAB(u) */
162                 if (cnt > 512) /* Attempted buffer overflow */
163                         break;
164                 memcpy(xuser,data,cnt);
165                 xuser[cnt] = '\0';
166                 pk_decode(xuser,user,&ck);
167                 auth_encrypt_user(user);
168                 Data(ap, SRA_CONTINUE, (void *)0, 0);
169
170                 return;
171
172         case SRA_PASS:
173                 if (cnt > 512) /* Attempted buffer overflow */
174                         break;
175                 /* decode KAB(P) */
176                 memcpy(xpass,data,cnt);
177                 xpass[cnt] = '\0';
178                 pk_decode(xpass,pass,&ck);
179
180                 /* check user's password */
181                 valid = check_user(user,pass);
182
183                 if(valid) {
184                         Data(ap, SRA_ACCEPT, (void *)0, 0);
185 #ifdef DES_ENCRYPTION
186                         skey.data = ck;
187                         skey.type = SK_DES;
188                         skey.length = 8;
189                         encrypt_session_key(&skey, 1);
190 #endif
191
192                         sra_valid = 1;
193                         auth_finished(ap, AUTH_VALID);
194                         if (auth_debug_mode) {
195                                 printf("SRA user accepted\r\n");
196                         }
197                 }
198                 else {
199                         Data(ap, SRA_CONTINUE, (void *)0, 0);
200 /*
201                         Data(ap, SRA_REJECT, (void *)0, 0);
202                         sra_valid = 0;
203                         auth_finished(ap, AUTH_REJECT);
204 */
205                         if (auth_debug_mode) {
206                                 printf("SRA user failed\r\n");
207                         }
208                 }
209                 return;
210
211         default:
212                 if (auth_debug_mode)
213                         printf("Unknown SRA option %d\r\n", data[-1]);
214         }
215 bad:
216         Data(ap, SRA_REJECT, 0, 0);
217         sra_valid = 0;
218         auth_finished(ap, AUTH_REJECT);
219 }
220
221 /* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
222 void
223 sra_reply(Authenticator *ap, unsigned char *data, int cnt)
224 {
225         extern char *telnet_gets();
226         char uprompt[256],tuser[256];
227         Session_Key skey;
228         int i;
229
230         if (cnt-- < 1)
231                 return;
232         switch (*data++) {
233
234         case SRA_KEY:
235                 /* calculate common key */
236                 if (cnt < HEXKEYBYTES) {
237                         if (auth_debug_mode) {
238                                 printf("SRA user rejected for bad PKB\r\n");
239                         }
240                         return;
241                 }
242                 memcpy(pkb,data,HEXKEYBYTES);
243                 pkb[HEXKEYBYTES] = '\0';                
244
245                 common_key(ska,pkb,&ik,&ck);
246
247         enc_user:
248
249                 /* encode user */
250                 memset(tuser,0,sizeof(tuser));
251                 sprintf(uprompt,"User (%s): ",UserNameRequested);
252                 telnet_gets(uprompt,tuser,255,1);
253                 if (tuser[0] == '\n' || tuser[0] == '\r' )
254                         strcpy(user,UserNameRequested);
255                 else {
256                         /* telnet_gets leaves the newline on */
257                         for(i=0;i<sizeof(tuser);i++) {
258                                 if (tuser[i] == '\n') {
259                                         tuser[i] = '\0';
260                                         break;
261                                 }
262                         }
263                         strcpy(user,tuser);
264                 }
265                 pk_encode(user,xuser,&ck);
266
267                 /* send it off */
268                 if (auth_debug_mode)
269                         printf("Sent KAB(U)\r\n");
270                 if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
271                         if (auth_debug_mode)
272                                 printf("Not enough room\r\n");
273                         return;
274                 }
275                 break;
276
277         case SRA_CONTINUE:
278                 if (passwd_sent) {
279                         passwd_sent = 0;
280                         printf("[ SRA login failed ]\r\n");
281                         goto enc_user;
282                 }
283                 /* encode password */
284                 memset(pass,0,sizeof(pass));
285                 telnet_gets("Password: ",pass,255,0);
286                 pk_encode(pass,xpass,&ck);
287                 /* send it off */
288                 if (auth_debug_mode)
289                         printf("Sent KAB(P)\r\n");
290                 if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
291                         if (auth_debug_mode)
292                                 printf("Not enough room\r\n");
293                         return;
294                 }
295                 passwd_sent = 1;
296                 break;
297
298         case SRA_REJECT:
299                 printf("[ SRA refuses authentication ]\r\n");
300                 printf("Trying plaintext login:\r\n");
301                 auth_finished(0,AUTH_REJECT);
302                 return;
303
304         case SRA_ACCEPT:
305                 printf("[ SRA accepts you ]\r\n");
306 #ifdef DES_ENCRYPTION
307                 skey.data = ck;
308                 skey.type = SK_DES;
309                 skey.length = 8;
310                 encrypt_session_key(&skey, 0);
311 #endif
312
313                 auth_finished(ap, AUTH_VALID);
314                 return;
315         default:
316                 if (auth_debug_mode)
317                         printf("Unknown SRA option %d\r\n", data[-1]);
318                 return;
319         }
320 }
321
322 int
323 sra_status(Authenticator *ap, char *name, int level)
324 {
325         if (level < AUTH_USER)
326                 return(level);
327         if (UserNameRequested && sra_valid) {
328                 strcpy(name, UserNameRequested);
329                 return(AUTH_VALID);
330         } else
331                 return(AUTH_USER);
332 }
333
334 #define BUMP(buf, len)          while (*(buf)) {++(buf), --(len);}
335 #define ADDC(buf, len, c)       if ((len) > 0) {*(buf)++ = (c); --(len);}
336
337 void
338 sra_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
339 {
340         char lbuf[32];
341         register int i;
342
343         buf[buflen-1] = '\0';           /* make sure its NULL terminated */
344         buflen -= 1;
345
346         switch(data[3]) {
347
348         case SRA_CONTINUE:
349                 strncpy((char *)buf, " CONTINUE ", buflen);
350                 goto common;
351
352         case SRA_REJECT:                /* Rejected (reason might follow) */
353                 strncpy((char *)buf, " REJECT ", buflen);
354                 goto common;
355
356         case SRA_ACCEPT:                /* Accepted (name might follow) */
357                 strncpy((char *)buf, " ACCEPT ", buflen);
358
359         common:
360                 BUMP(buf, buflen);
361                 if (cnt <= 4)
362                         break;
363                 ADDC(buf, buflen, '"');
364                 for (i = 4; i < cnt; i++)
365                         ADDC(buf, buflen, data[i]);
366                 ADDC(buf, buflen, '"');
367                 ADDC(buf, buflen, '\0');
368                 break;
369
370         case SRA_KEY:                   /* Authentication data follows */
371                 strncpy((char *)buf, " KEY ", buflen);
372                 goto common2;
373
374         case SRA_USER:
375                 strncpy((char *)buf, " USER ", buflen);
376                 goto common2;
377
378         case SRA_PASS:
379                 strncpy((char *)buf, " PASS ", buflen);
380                 goto common2;
381
382         default:
383                 sprintf(lbuf, " %d (unknown)", data[3]);
384                 strncpy((char *)buf, lbuf, buflen);
385         common2:
386                 BUMP(buf, buflen);
387                 for (i = 4; i < cnt; i++) {
388                         sprintf(lbuf, " %d", data[i]);
389                         strncpy((char *)buf, lbuf, buflen);
390                         BUMP(buf, buflen);
391                 }
392                 break;
393         }
394 }
395
396 struct  passwd *pw;
397
398 /*
399  * Helper function for sgetpwnam().
400  */
401 char *
402 sgetsave(char *s)
403 {
404         char *new = malloc((unsigned) strlen(s) + 1);
405
406         if (new == NULL) {
407                 return(NULL);
408         }
409         (void) strcpy(new, s);
410         return (new);
411 }
412
413 struct passwd *
414 sgetpwnam(char *name)
415 {
416         static struct passwd save;
417         register struct passwd *p;
418         char *sgetsave();
419
420         if ((p = getpwnam(name)) == NULL)
421                 return (p);
422         if (save.pw_name) {
423                 free(save.pw_name);
424                 free(save.pw_passwd);
425                 free(save.pw_gecos);
426                 free(save.pw_dir);
427                 free(save.pw_shell);
428         }
429         save = *p;
430         save.pw_name = sgetsave(p->pw_name);
431         save.pw_passwd = sgetsave(p->pw_passwd);
432         save.pw_gecos = sgetsave(p->pw_gecos);
433         save.pw_dir = sgetsave(p->pw_dir);
434         save.pw_shell = sgetsave(p->pw_shell);
435 #if 0
436 syslog(LOG_WARNING,"%s\n",save.pw_name);
437 syslog(LOG_WARNING,"%s\n",save.pw_passwd);
438 syslog(LOG_WARNING,"%s\n",save.pw_gecos);
439 syslog(LOG_WARNING,"%s\n",save.pw_dir);
440 #endif
441 #ifdef USE_SHADOW
442         {
443                 struct spwd *sp;
444                 sp = getspnam(name);
445                 free(save.pw_passwd);
446                 save.pw_passwd  = sgetsave(sp->sp_pwdp);
447         }
448 #endif 
449         return (&save);
450 }
451
452 static int
453 isroot(const char *user)
454 {
455         struct passwd *pw;
456
457         if ((pw=getpwnam(user))==NULL)
458                 return 0;
459         return (!pw->pw_uid);
460 }
461
462 static int
463 rootterm(char *ttyn)
464 {
465         struct ttyent *t;
466
467         return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
468 }
469
470 #ifdef NOPAM
471 static int
472 check_user(const char *name, const char *pass)
473 {
474         register char *cp;
475         char *xpasswd, *salt;
476
477         if (isroot(name) && !rootterm(line))
478         {
479                 crypt("AA","*"); /* Waste some time to simulate success */
480                 return(0);
481         }
482
483         if (pw = sgetpwnam(name)) {
484                 if (pw->pw_shell == NULL) {
485                         pw = (struct passwd *) NULL;
486                         return(0);
487                 }
488
489                 salt = pw->pw_passwd;
490                 xpasswd = crypt(pass, salt);
491                 /* The strcmp does not catch null passwords! */
492                 if (pw == NULL || *pw->pw_passwd == '\0' ||
493                         strcmp(xpasswd, pw->pw_passwd)) {
494                         pw = (struct passwd *) NULL;
495                         return(0);
496                 }
497                 return(1);
498         }
499         return(0);
500 }
501 #else
502
503 /*
504  * The following is stolen from ftpd, which stole it from the imap-uw
505  * PAM module and login.c. It is needed because we can't really
506  * "converse" with the user, having already gone to the trouble of
507  * getting their username and password through an encrypted channel.
508  */
509
510 #define COPY_STRING(s) (s ? strdup(s):NULL)
511
512 struct cred_t {
513         const char *uname;
514         const char *pass;
515 };
516 typedef struct cred_t cred_t;
517
518 int
519 auth_conv(int num_msg, const struct pam_message **msg,
520         struct pam_response **resp, void *appdata)
521 {
522         int i;
523         cred_t *cred = (cred_t *) appdata;
524         struct pam_response *reply =
525                 malloc(sizeof(struct pam_response) * num_msg);
526
527         if (reply == NULL)
528                 return PAM_BUF_ERR;
529
530         for (i = 0; i < num_msg; i++) {
531                 switch (msg[i]->msg_style) {
532                 case PAM_PROMPT_ECHO_ON:        /* assume want user name */
533                         reply[i].resp_retcode = PAM_SUCCESS;
534                         reply[i].resp = COPY_STRING(cred->uname);
535                         /* PAM frees resp. */
536                         break;
537                 case PAM_PROMPT_ECHO_OFF:       /* assume want password */
538                         reply[i].resp_retcode = PAM_SUCCESS;
539                         reply[i].resp = COPY_STRING(cred->pass);
540                         /* PAM frees resp. */
541                         break;
542                 case PAM_TEXT_INFO:
543                 case PAM_ERROR_MSG:
544                         reply[i].resp_retcode = PAM_SUCCESS;
545                         reply[i].resp = NULL;
546                         break;
547                 default:                        /* unknown message style */
548                         free(reply);
549                         return PAM_CONV_ERR;
550                 }
551         }
552
553         *resp = reply;
554         return PAM_SUCCESS;
555 }
556
557 /*
558  * The PAM version as a side effect may put a new username in *name.
559  */
560 static int
561 check_user(const char *name, const char *pass)
562 {
563         pam_handle_t *pamh = NULL;
564         const void *item;
565         int rval;
566         int e;
567         cred_t auth_cred = { name, pass };
568         struct pam_conv conv = { &auth_conv, &auth_cred };
569
570         e = pam_start("telnetd", name, &conv, &pamh);
571         if (e != PAM_SUCCESS) {
572                 syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
573                 return 0;
574         }
575
576 #if 0 /* Where can we find this value? */
577         e = pam_set_item(pamh, PAM_RHOST, remotehost);
578         if (e != PAM_SUCCESS) {
579                 syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
580                         pam_strerror(pamh, e));
581                 return 0;
582         }
583 #endif
584
585         e = pam_authenticate(pamh, 0);
586         switch (e) {
587         case PAM_SUCCESS:
588                 /*
589                  * With PAM we support the concept of a "template"
590                  * user.  The user enters a login name which is
591                  * authenticated by PAM, usually via a remote service
592                  * such as RADIUS or TACACS+.  If authentication
593                  * succeeds, a different but related "template" name
594                  * is used for setting the credentials, shell, and
595                  * home directory.  The name the user enters need only
596                  * exist on the remote authentication server, but the
597                  * template name must be present in the local password
598                  * database.
599                  *
600                  * This is supported by two various mechanisms in the
601                  * individual modules.  However, from the application's
602                  * point of view, the template user is always passed
603                  * back as a changed value of the PAM_USER item.
604                  */
605                 if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
606                     PAM_SUCCESS) {
607                         strcpy((char *) name, (const char *) item);
608                 } else
609                         syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
610                         pam_strerror(pamh, e));
611                 if (isroot(name) && !rootterm(line))
612                         rval = 0;
613                 else
614                         rval = 1;
615                 break;
616
617         case PAM_AUTH_ERR:
618         case PAM_USER_UNKNOWN:
619         case PAM_MAXTRIES:
620                 rval = 0;
621         break;
622
623         default:
624                 syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
625                 rval = 0;
626                 break;
627         }
628
629         if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
630                 syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
631                 rval = 0;
632         }
633         return rval;
634 }
635
636 #endif
637
638 #endif
639