6 #include <arpa/telnet.h>
18 #include <security/pam_appl.h>
32 char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
33 char *user,*pass,*xuser,*xpass;
37 extern int auth_debug_mode;
40 static int sra_valid = 0;
41 static int passwd_sent = 0;
43 static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
48 #define SRA_CONTINUE 2
53 static int check_user(const char *, const char *);
55 /* support routine to send out authentication message */
57 Data(Authenticator *ap, int type, void *d, int c)
59 unsigned char *p = str_data + 4;
60 unsigned char *cd = (unsigned char *)d;
63 c = strlen((char *)cd);
65 if (auth_debug_mode) {
66 printf("%s:%d: [%d] (%d)",
67 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
77 if ((*p++ = *cd++) == IAC)
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));
88 sra_init(Authenticator *ap, int server)
91 str_data[3] = TELQUAL_REPLY;
93 str_data[3] = TELQUAL_IS;
95 user = (char *)malloc(256);
96 xuser = (char *)malloc(513);
97 pass = (char *)malloc(256);
98 xpass = (char *)malloc(513);
100 if (user == NULL || xuser == NULL || pass == NULL || xpass ==
102 return 0; /* malloc failed */
110 /* client received a go-ahead for sra */
112 sra_send(Authenticator *ap)
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)) {
121 printf("Not enough room for authentication data\r\n");
128 /* server received an IS -- could be SRA KEY, USER, or PASS */
130 sra_is(Authenticator *ap, unsigned char *data, int cnt)
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");
149 printf("Sent pka\r\n");
150 if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
152 printf("Not enough room\r\n");
155 memcpy(pkb,data,HEXKEYBYTES);
156 pkb[HEXKEYBYTES] = '\0';
157 common_key(ska,pkb,&ik,&ck);
162 if (cnt > 512) /* Attempted buffer overflow */
164 memcpy(xuser,data,cnt);
166 pk_decode(xuser,user,&ck);
167 auth_encrypt_user(user);
168 Data(ap, SRA_CONTINUE, (void *)0, 0);
173 if (cnt > 512) /* Attempted buffer overflow */
176 memcpy(xpass,data,cnt);
178 pk_decode(xpass,pass,&ck);
180 /* check user's password */
181 valid = check_user(user,pass);
184 Data(ap, SRA_ACCEPT, (void *)0, 0);
185 #ifdef DES_ENCRYPTION
189 encrypt_session_key(&skey, 1);
193 auth_finished(ap, AUTH_VALID);
194 if (auth_debug_mode) {
195 printf("SRA user accepted\r\n");
199 Data(ap, SRA_CONTINUE, (void *)0, 0);
201 Data(ap, SRA_REJECT, (void *)0, 0);
203 auth_finished(ap, AUTH_REJECT);
205 if (auth_debug_mode) {
206 printf("SRA user failed\r\n");
213 printf("Unknown SRA option %d\r\n", data[-1]);
216 Data(ap, SRA_REJECT, 0, 0);
218 auth_finished(ap, AUTH_REJECT);
221 /* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
223 sra_reply(Authenticator *ap, unsigned char *data, int cnt)
225 extern char *telnet_gets();
226 char uprompt[256],tuser[256];
235 /* calculate common key */
236 if (cnt < HEXKEYBYTES) {
237 if (auth_debug_mode) {
238 printf("SRA user rejected for bad PKB\r\n");
242 memcpy(pkb,data,HEXKEYBYTES);
243 pkb[HEXKEYBYTES] = '\0';
245 common_key(ska,pkb,&ik,&ck);
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);
256 /* telnet_gets leaves the newline on */
257 for(i=0;i<sizeof(tuser);i++) {
258 if (tuser[i] == '\n') {
265 pk_encode(user,xuser,&ck);
269 printf("Sent KAB(U)\r\n");
270 if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
272 printf("Not enough room\r\n");
280 printf("[ SRA login failed ]\r\n");
283 /* encode password */
284 memset(pass,0,sizeof(pass));
285 telnet_gets("Password: ",pass,255,0);
286 pk_encode(pass,xpass,&ck);
289 printf("Sent KAB(P)\r\n");
290 if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
292 printf("Not enough room\r\n");
299 printf("[ SRA refuses authentication ]\r\n");
300 printf("Trying plaintext login:\r\n");
301 auth_finished(0,AUTH_REJECT);
305 printf("[ SRA accepts you ]\r\n");
306 #ifdef DES_ENCRYPTION
310 encrypt_session_key(&skey, 0);
313 auth_finished(ap, AUTH_VALID);
317 printf("Unknown SRA option %d\r\n", data[-1]);
323 sra_status(Authenticator *ap, char *name, int level)
325 if (level < AUTH_USER)
327 if (UserNameRequested && sra_valid) {
328 strcpy(name, UserNameRequested);
334 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
335 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
338 sra_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
343 buf[buflen-1] = '\0'; /* make sure its NULL terminated */
349 strncpy((char *)buf, " CONTINUE ", buflen);
352 case SRA_REJECT: /* Rejected (reason might follow) */
353 strncpy((char *)buf, " REJECT ", buflen);
356 case SRA_ACCEPT: /* Accepted (name might follow) */
357 strncpy((char *)buf, " ACCEPT ", buflen);
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');
370 case SRA_KEY: /* Authentication data follows */
371 strncpy((char *)buf, " KEY ", buflen);
375 strncpy((char *)buf, " USER ", buflen);
379 strncpy((char *)buf, " PASS ", buflen);
383 sprintf(lbuf, " %d (unknown)", data[3]);
384 strncpy((char *)buf, lbuf, buflen);
387 for (i = 4; i < cnt; i++) {
388 sprintf(lbuf, " %d", data[i]);
389 strncpy((char *)buf, lbuf, buflen);
399 * Helper function for sgetpwnam().
404 char *new = malloc((unsigned) strlen(s) + 1);
409 (void) strcpy(new, s);
414 sgetpwnam(char *name)
416 static struct passwd save;
417 register struct passwd *p;
420 if ((p = getpwnam(name)) == NULL)
424 free(save.pw_passwd);
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);
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);
445 free(save.pw_passwd);
446 save.pw_passwd = sgetsave(sp->sp_pwdp);
453 isroot(const char *user)
457 if ((pw=getpwnam(user))==NULL)
459 return (!pw->pw_uid);
467 return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
472 check_user(const char *name, const char *pass)
475 char *xpasswd, *salt;
477 if (isroot(name) && !rootterm(line))
479 crypt("AA","*"); /* Waste some time to simulate success */
483 if (pw = sgetpwnam(name)) {
484 if (pw->pw_shell == NULL) {
485 pw = (struct passwd *) NULL;
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;
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.
510 #define COPY_STRING(s) (s ? strdup(s):NULL)
516 typedef struct cred_t cred_t;
519 auth_conv(int num_msg, const struct pam_message **msg,
520 struct pam_response **resp, void *appdata)
523 cred_t *cred = (cred_t *) appdata;
524 struct pam_response *reply =
525 malloc(sizeof(struct pam_response) * num_msg);
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. */
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. */
544 reply[i].resp_retcode = PAM_SUCCESS;
545 reply[i].resp = NULL;
547 default: /* unknown message style */
558 * The PAM version as a side effect may put a new username in *name.
561 check_user(const char *name, const char *pass)
563 pam_handle_t *pamh = NULL;
567 cred_t auth_cred = { name, pass };
568 struct pam_conv conv = { &auth_conv, &auth_cred };
570 e = pam_start("telnetd", name, &conv, &pamh);
571 if (e != PAM_SUCCESS) {
572 syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
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));
585 e = pam_authenticate(pamh, 0);
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
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.
605 if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
607 strcpy((char *) name, (const char *) item);
609 syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
610 pam_strerror(pamh, e));
611 if (isroot(name) && !rootterm(line))
618 case PAM_USER_UNKNOWN:
624 syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
629 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
630 syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));