sra.c revision 76610
163248Speter/* $FreeBSD: head/contrib/telnet/libtelnet/sra.c 76610 2001-05-15 04:47:14Z nsayer $ */ 263248Speter 349887Snsayer#ifdef SRA 449887Snsayer#include <sys/types.h> 549887Snsayer#include <arpa/telnet.h> 649887Snsayer#include <stdio.h> 749887Snsayer#ifdef __STDC__ 849887Snsayer#include <stdlib.h> 949887Snsayer#endif 1049887Snsayer#ifdef NO_STRING_H 1149887Snsayer#include <strings.h> 1249887Snsayer#else 1349887Snsayer#include <string.h> 1449887Snsayer#endif 1549887Snsayer 1676339Snsayer#if !defined(NOPAM) 1776339Snsayer#include <security/pam_appl.h> 1876339Snsayer#endif 1976339Snsayer 2076610Snsayer#include <ttyent.h> 2176610Snsayer 2249887Snsayer#include "auth.h" 2349887Snsayer#include "misc.h" 2449887Snsayer#include "encrypt.h" 2549887Snsayer#include "pk.h" 2649887Snsayer 2749887Snsayerchar pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1]; 2849887Snsayerchar *user,*pass,*xuser,*xpass; 2949887SnsayerDesData ck; 3049887SnsayerIdeaData ik; 3149887Snsayer 3249887Snsayerextern int auth_debug_mode; 3376610Snsayerextern char *line; 3476610Snsayer 3549887Snsayerstatic sra_valid = 0; 3649887Snsayerstatic passwd_sent = 0; 3749887Snsayer 3849887Snsayerstatic unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, 3949887Snsayer AUTHTYPE_SRA, }; 4049887Snsayer 4149887Snsayer#define SRA_KEY 0 4249887Snsayer#define SRA_USER 1 4349887Snsayer#define SRA_CONTINUE 2 4449887Snsayer#define SRA_PASS 3 4549887Snsayer#define SRA_ACCEPT 4 4649887Snsayer#define SRA_REJECT 5 4749887Snsayer 4849887Snsayer/* support routine to send out authentication message */ 4949887Snsayerstatic int Data(ap, type, d, c) 5049887SnsayerAuthenticator *ap; 5149887Snsayerint type; 5249887Snsayervoid *d; 5349887Snsayerint c; 5449887Snsayer{ 5549887Snsayer unsigned char *p = str_data + 4; 5649887Snsayer unsigned char *cd = (unsigned char *)d; 5749887Snsayer 5849887Snsayer if (c == -1) 5949887Snsayer c = strlen((char *)cd); 6049887Snsayer 6149887Snsayer if (auth_debug_mode) { 6249887Snsayer printf("%s:%d: [%d] (%d)", 6349887Snsayer str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", 6449887Snsayer str_data[3], 6549887Snsayer type, c); 6649887Snsayer printd(d, c); 6749887Snsayer printf("\r\n"); 6849887Snsayer } 6949887Snsayer *p++ = ap->type; 7049887Snsayer *p++ = ap->way; 7149887Snsayer *p++ = type; 7249887Snsayer while (c-- > 0) { 7349887Snsayer if ((*p++ = *cd++) == IAC) 7449887Snsayer *p++ = IAC; 7549887Snsayer } 7649887Snsayer *p++ = IAC; 7749887Snsayer *p++ = SE; 7849887Snsayer if (str_data[3] == TELQUAL_IS) 7949887Snsayer printsub('>', &str_data[2], p - (&str_data[2])); 8049887Snsayer return(net_write(str_data, p - str_data)); 8149887Snsayer} 8249887Snsayer 8349887Snsayerint sra_init(ap, server) 8449887SnsayerAuthenticator *ap; 8549887Snsayerint server; 8649887Snsayer{ 8749887Snsayer if (server) 8849887Snsayer str_data[3] = TELQUAL_REPLY; 8949887Snsayer else 9049887Snsayer str_data[3] = TELQUAL_IS; 9149887Snsayer 9249887Snsayer user = (char *)malloc(256); 9349887Snsayer xuser = (char *)malloc(512); 9449887Snsayer pass = (char *)malloc(256); 9549887Snsayer xpass = (char *)malloc(512); 9649887Snsayer passwd_sent = 0; 9749887Snsayer 9849887Snsayer genkeys(pka,ska); 9949887Snsayer return(1); 10049887Snsayer} 10149887Snsayer 10249887Snsayer/* client received a go-ahead for sra */ 10349887Snsayerint sra_send(ap) 10449887SnsayerAuthenticator *ap; 10549887Snsayer{ 10649887Snsayer /* send PKA */ 10749887Snsayer 10849887Snsayer if (auth_debug_mode) 10949887Snsayer printf("Sent PKA to server.\r\n" ); 11049887Snsayer printf("Trying SRA secure login:\r\n"); 11149887Snsayer if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) { 11249887Snsayer if (auth_debug_mode) 11349887Snsayer printf("Not enough room for authentication data\r\n"); 11449887Snsayer return(0); 11549887Snsayer } 11649887Snsayer 11749887Snsayer return(1); 11849887Snsayer} 11949887Snsayer 12049887Snsayer/* server received an IS -- could be SRA KEY, USER, or PASS */ 12149887Snsayervoid sra_is(ap, data, cnt) 12249887SnsayerAuthenticator *ap; 12349887Snsayerunsigned char *data; 12449887Snsayerint cnt; 12549887Snsayer{ 12649887Snsayer int valid; 12749887Snsayer Session_Key skey; 12849887Snsayer 12949887Snsayer if (cnt-- < 1) 13049887Snsayer return; 13149887Snsayer switch (*data++) { 13249887Snsayer 13349887Snsayer case SRA_KEY: 13449887Snsayer if (cnt < HEXKEYBYTES) { 13549887Snsayer Data(ap, SRA_REJECT, (void *)0, 0); 13649887Snsayer auth_finished(ap, AUTH_USER); 13749887Snsayer if (auth_debug_mode) { 13849887Snsayer printf("SRA user rejected for bad PKB\r\n"); 13949887Snsayer } 14049887Snsayer return; 14149887Snsayer } 14249887Snsayer if (auth_debug_mode) 14349887Snsayer printf("Sent pka\r\n"); 14449887Snsayer if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) { 14549887Snsayer if (auth_debug_mode) 14649887Snsayer printf("Not enough room\r\n"); 14749887Snsayer return; 14849887Snsayer } 14949887Snsayer memcpy(pkb,data,HEXKEYBYTES); 15049887Snsayer pkb[HEXKEYBYTES] = '\0'; 15149887Snsayer common_key(ska,pkb,&ik,&ck); 15249887Snsayer break; 15349887Snsayer 15449887Snsayer case SRA_USER: 15549887Snsayer /* decode KAB(u) */ 15649887Snsayer memcpy(xuser,data,cnt); 15749887Snsayer xuser[cnt] = '\0'; 15849887Snsayer pk_decode(xuser,user,&ck); 15949887Snsayer auth_encrypt_user(user); 16049887Snsayer Data(ap, SRA_CONTINUE, (void *)0, 0); 16149887Snsayer 16249887Snsayer break; 16349887Snsayer 16449887Snsayer case SRA_PASS: 16549887Snsayer /* decode KAB(P) */ 16649887Snsayer memcpy(xpass,data,cnt); 16749887Snsayer xpass[cnt] = '\0'; 16849887Snsayer pk_decode(xpass,pass,&ck); 16949887Snsayer 17049887Snsayer /* check user's password */ 17149887Snsayer valid = check_user(user,pass); 17249887Snsayer 17349887Snsayer if(valid) { 17449887Snsayer Data(ap, SRA_ACCEPT, (void *)0, 0); 17549887Snsayer#ifdef DES_ENCRYPTION 17649887Snsayer skey.data = ck; 17749887Snsayer skey.type = SK_DES; 17849887Snsayer skey.length = 8; 17949887Snsayer encrypt_session_key(&skey, 1); 18049887Snsayer#endif 18149887Snsayer 18249887Snsayer sra_valid = 1; 18349887Snsayer auth_finished(ap, AUTH_VALID); 18449887Snsayer if (auth_debug_mode) { 18549887Snsayer printf("SRA user accepted\r\n"); 18649887Snsayer } 18749887Snsayer } 18849887Snsayer else { 18949887Snsayer Data(ap, SRA_CONTINUE, (void *)0, 0); 19049887Snsayer/* 19149887Snsayer Data(ap, SRA_REJECT, (void *)0, 0); 19249887Snsayer sra_valid = 0; 19349887Snsayer auth_finished(ap, AUTH_REJECT); 19449887Snsayer*/ 19549887Snsayer if (auth_debug_mode) { 19649887Snsayer printf("SRA user failed\r\n"); 19749887Snsayer } 19849887Snsayer } 19949887Snsayer break; 20049887Snsayer 20149887Snsayer default: 20249887Snsayer if (auth_debug_mode) 20349887Snsayer printf("Unknown SRA option %d\r\n", data[-1]); 20449887Snsayer Data(ap, SRA_REJECT, 0, 0); 20549887Snsayer sra_valid = 0; 20649887Snsayer auth_finished(ap, AUTH_REJECT); 20749887Snsayer break; 20849887Snsayer } 20949887Snsayer} 21049887Snsayer 21149887Snsayerextern char *getpass(); 21249887Snsayer 21349887Snsayer/* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */ 21449887Snsayervoid sra_reply(ap, data, cnt) 21549887SnsayerAuthenticator *ap; 21649887Snsayerunsigned char *data; 21749887Snsayerint cnt; 21849887Snsayer{ 21949887Snsayer extern char *telnet_gets(); 22049887Snsayer char uprompt[256],tuser[256]; 22149887Snsayer Session_Key skey; 22249887Snsayer int i; 22349887Snsayer 22449887Snsayer if (cnt-- < 1) 22549887Snsayer return; 22649887Snsayer switch (*data++) { 22749887Snsayer 22849887Snsayer case SRA_KEY: 22949887Snsayer /* calculate common key */ 23049887Snsayer if (cnt < HEXKEYBYTES) { 23149887Snsayer if (auth_debug_mode) { 23249887Snsayer printf("SRA user rejected for bad PKB\r\n"); 23349887Snsayer } 23449887Snsayer return; 23549887Snsayer } 23649887Snsayer memcpy(pkb,data,HEXKEYBYTES); 23749887Snsayer pkb[HEXKEYBYTES] = '\0'; 23849887Snsayer 23949887Snsayer common_key(ska,pkb,&ik,&ck); 24049887Snsayer 24149887Snsayer enc_user: 24249887Snsayer 24349887Snsayer /* encode user */ 24449887Snsayer memset(tuser,0,sizeof(tuser)); 24549887Snsayer sprintf(uprompt,"User (%s): ",UserNameRequested); 24649887Snsayer telnet_gets(uprompt,tuser,255,1); 24749887Snsayer if (tuser[0] == '\n' || tuser[0] == '\r' ) 24849887Snsayer strcpy(user,UserNameRequested); 24949887Snsayer else { 25049887Snsayer /* telnet_gets leaves the newline on */ 25149887Snsayer for(i=0;i<sizeof(tuser);i++) { 25249887Snsayer if (tuser[i] == '\n') { 25349887Snsayer tuser[i] = '\0'; 25449887Snsayer break; 25549887Snsayer } 25649887Snsayer } 25749887Snsayer strcpy(user,tuser); 25849887Snsayer } 25949887Snsayer pk_encode(user,xuser,&ck); 26049887Snsayer 26149887Snsayer /* send it off */ 26249887Snsayer if (auth_debug_mode) 26349887Snsayer printf("Sent KAB(U)\r\n"); 26449887Snsayer if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) { 26549887Snsayer if (auth_debug_mode) 26649887Snsayer printf("Not enough room\r\n"); 26749887Snsayer return; 26849887Snsayer } 26949887Snsayer break; 27049887Snsayer 27149887Snsayer case SRA_CONTINUE: 27249887Snsayer if (passwd_sent) { 27349887Snsayer passwd_sent = 0; 27449887Snsayer printf("[ SRA login failed ]\r\n"); 27549887Snsayer goto enc_user; 27649887Snsayer } 27749887Snsayer /* encode password */ 27849887Snsayer memset(pass,0,sizeof(pass)); 27949887Snsayer telnet_gets("Password: ",pass,255,0); 28049887Snsayer pk_encode(pass,xpass,&ck); 28149887Snsayer /* send it off */ 28249887Snsayer if (auth_debug_mode) 28349887Snsayer printf("Sent KAB(P)\r\n"); 28449887Snsayer if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) { 28549887Snsayer if (auth_debug_mode) 28649887Snsayer printf("Not enough room\r\n"); 28749887Snsayer return; 28849887Snsayer } 28949887Snsayer passwd_sent = 1; 29049887Snsayer break; 29149887Snsayer 29249887Snsayer case SRA_REJECT: 29349887Snsayer printf("[ SRA refuses authentication ]\r\n"); 29449887Snsayer printf("Trying plaintext login:\r\n"); 29549887Snsayer auth_finished(0,AUTH_REJECT); 29649887Snsayer return; 29749887Snsayer 29849887Snsayer case SRA_ACCEPT: 29949887Snsayer printf("[ SRA accepts you ]\r\n"); 30049887Snsayer#ifdef DES_ENCRYPTION 30149887Snsayer skey.data = ck; 30249887Snsayer skey.type = SK_DES; 30349887Snsayer skey.length = 8; 30449887Snsayer encrypt_session_key(&skey, 0); 30549887Snsayer#endif 30649887Snsayer 30749887Snsayer auth_finished(ap, AUTH_VALID); 30849887Snsayer return; 30949887Snsayer default: 31049887Snsayer if (auth_debug_mode) 31149887Snsayer printf("Unknown SRA option %d\r\n", data[-1]); 31249887Snsayer return; 31349887Snsayer } 31449887Snsayer} 31549887Snsayer 31649887Snsayerint sra_status(ap, name, level) 31749887SnsayerAuthenticator *ap; 31849887Snsayerchar *name; 31949887Snsayerint level; 32049887Snsayer{ 32149887Snsayer if (level < AUTH_USER) 32249887Snsayer return(level); 32349887Snsayer if (UserNameRequested && sra_valid) { 32449887Snsayer strcpy(name, UserNameRequested); 32549887Snsayer return(AUTH_VALID); 32649887Snsayer } else 32749887Snsayer return(AUTH_USER); 32849887Snsayer} 32949887Snsayer 33049887Snsayer#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 33149887Snsayer#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 33249887Snsayer 33349887Snsayervoid sra_printsub(data, cnt, buf, buflen) 33449887Snsayerunsigned char *data, *buf; 33549887Snsayerint cnt, buflen; 33649887Snsayer{ 33749887Snsayer char lbuf[32]; 33849887Snsayer register int i; 33949887Snsayer 34049887Snsayer buf[buflen-1] = '\0'; /* make sure its NULL terminated */ 34149887Snsayer buflen -= 1; 34249887Snsayer 34349887Snsayer switch(data[3]) { 34449887Snsayer 34549887Snsayer case SRA_CONTINUE: 34649887Snsayer strncpy((char *)buf, " CONTINUE ", buflen); 34749887Snsayer goto common; 34849887Snsayer 34949887Snsayer case SRA_REJECT: /* Rejected (reason might follow) */ 35049887Snsayer strncpy((char *)buf, " REJECT ", buflen); 35149887Snsayer goto common; 35249887Snsayer 35349887Snsayer case SRA_ACCEPT: /* Accepted (name might follow) */ 35449887Snsayer strncpy((char *)buf, " ACCEPT ", buflen); 35549887Snsayer 35649887Snsayer common: 35749887Snsayer BUMP(buf, buflen); 35849887Snsayer if (cnt <= 4) 35949887Snsayer break; 36049887Snsayer ADDC(buf, buflen, '"'); 36149887Snsayer for (i = 4; i < cnt; i++) 36249887Snsayer ADDC(buf, buflen, data[i]); 36349887Snsayer ADDC(buf, buflen, '"'); 36449887Snsayer ADDC(buf, buflen, '\0'); 36549887Snsayer break; 36649887Snsayer 36749887Snsayer case SRA_KEY: /* Authentication data follows */ 36849887Snsayer strncpy((char *)buf, " KEY ", buflen); 36949887Snsayer goto common2; 37049887Snsayer 37149887Snsayer case SRA_USER: 37249887Snsayer strncpy((char *)buf, " USER ", buflen); 37349887Snsayer goto common2; 37449887Snsayer 37549887Snsayer case SRA_PASS: 37649887Snsayer strncpy((char *)buf, " PASS ", buflen); 37749887Snsayer goto common2; 37849887Snsayer 37949887Snsayer default: 38049887Snsayer sprintf(lbuf, " %d (unknown)", data[3]); 38149887Snsayer strncpy((char *)buf, lbuf, buflen); 38249887Snsayer common2: 38349887Snsayer BUMP(buf, buflen); 38449887Snsayer for (i = 4; i < cnt; i++) { 38549887Snsayer sprintf(lbuf, " %d", data[i]); 38649887Snsayer strncpy((char *)buf, lbuf, buflen); 38749887Snsayer BUMP(buf, buflen); 38849887Snsayer } 38949887Snsayer break; 39049887Snsayer } 39149887Snsayer} 39249887Snsayer 39349887Snsayerstruct passwd *pw; 39449887Snsayer 39549887Snsayer/* 39649887Snsayer * Helper function for sgetpwnam(). 39749887Snsayer */ 39849887Snsayerchar * 39949887Snsayersgetsave(s) 40049887Snsayer char *s; 40149887Snsayer{ 40249887Snsayer char *new = malloc((unsigned) strlen(s) + 1); 40349887Snsayer 40449887Snsayer if (new == NULL) { 40549887Snsayer return(NULL); 40649887Snsayer } 40749887Snsayer (void) strcpy(new, s); 40849887Snsayer return (new); 40949887Snsayer} 41049887Snsayer 41149887Snsayer#include <pwd.h> 41249887Snsayer#include <syslog.h> 41349887Snsayer#ifdef USE_SHADOW 41449887Snsayer#include <shadow.h> 41549887Snsayer#endif 41649887Snsayer 41749887Snsayer 41849887Snsayerstruct passwd * 41949887Snsayersgetpwnam(name) 42049887Snsayer char *name; 42149887Snsayer{ 42249887Snsayer static struct passwd save; 42349887Snsayer register struct passwd *p; 42449887Snsayer char *sgetsave(); 42549887Snsayer 42649887Snsayer if ((p = getpwnam(name)) == NULL) 42749887Snsayer return (p); 42849887Snsayer if (save.pw_name) { 42949887Snsayer free(save.pw_name); 43049887Snsayer free(save.pw_passwd); 43149887Snsayer free(save.pw_gecos); 43249887Snsayer free(save.pw_dir); 43349887Snsayer free(save.pw_shell); 43449887Snsayer } 43549887Snsayer save = *p; 43649887Snsayer save.pw_name = sgetsave(p->pw_name); 43749887Snsayer save.pw_passwd = sgetsave(p->pw_passwd); 43849887Snsayer save.pw_gecos = sgetsave(p->pw_gecos); 43949887Snsayer save.pw_dir = sgetsave(p->pw_dir); 44049887Snsayer save.pw_shell = sgetsave(p->pw_shell); 44149887Snsayer#if 0 44249887Snsayersyslog(LOG_WARNING,"%s\n",save.pw_name); 44349887Snsayersyslog(LOG_WARNING,"%s\n",save.pw_passwd); 44449887Snsayersyslog(LOG_WARNING,"%s\n",save.pw_gecos); 44549887Snsayersyslog(LOG_WARNING,"%s\n",save.pw_dir); 44649887Snsayer#endif 44749887Snsayer#ifdef USE_SHADOW 44849887Snsayer { 44949887Snsayer struct spwd *sp; 45049887Snsayer sp = getspnam(name); 45149887Snsayer free(save.pw_passwd); 45249887Snsayer save.pw_passwd = sgetsave(sp->sp_pwdp); 45349887Snsayer } 45449887Snsayer#endif 45549887Snsayer return (&save); 45649887Snsayer} 45749887Snsayer 45876610Snsayerstatic int 45976610Snsayerisroot(user) 46076610Snsayerchar *user; 46176610Snsayer{ 46276610Snsayer struct passwd *pw; 46376610Snsayer 46476610Snsayer if ((pw=getpwnam(user))==NULL) 46576610Snsayer return 0; 46676610Snsayer return (!pw->pw_uid); 46776610Snsayer} 46876610Snsayer 46976610Snsayerstatic int 47076610Snsayerrootterm(ttyn) 47176610Snsayerchar *ttyn; 47276610Snsayer{ 47376610Snsayer struct ttyent *t; 47476610Snsayer 47576610Snsayer return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE); 47676610Snsayer} 47776610Snsayer 47876339Snsayer#ifdef NOPAM 47949887Snsayerchar *crypt(); 48049887Snsayer 48149887Snsayerint check_user(name, pass) 48249887Snsayerchar *name; 48349887Snsayerchar *pass; 48449887Snsayer{ 48549887Snsayer register char *cp; 48649887Snsayer char *xpasswd, *salt; 48749887Snsayer 48876610Snsayer if (isroot(name) && !rootterm(line)) 48976610Snsayer { 49076610Snsayer crypt("AA","*"); /* Waste some time to simulate success */ 49176610Snsayer return(0); 49276610Snsayer } 49376610Snsayer 49449887Snsayer if (pw = sgetpwnam(name)) { 49549887Snsayer if (pw->pw_shell == NULL) { 49649887Snsayer pw = (struct passwd *) NULL; 49749887Snsayer return(0); 49849887Snsayer } 49949887Snsayer 50049887Snsayer salt = pw->pw_passwd; 50149887Snsayer xpasswd = crypt(pass, salt); 50249887Snsayer /* The strcmp does not catch null passwords! */ 50349887Snsayer if (pw == NULL || *pw->pw_passwd == '\0' || 50449887Snsayer strcmp(xpasswd, pw->pw_passwd)) { 50549887Snsayer pw = (struct passwd *) NULL; 50649887Snsayer return(0); 50749887Snsayer } 50849887Snsayer return(1); 50949887Snsayer } 51049887Snsayer return(0); 51149887Snsayer} 51276339Snsayer#else 51349887Snsayer 51476339Snsayer/* 51576339Snsayer * The following is stolen from ftpd, which stole it from the imap-uw 51676339Snsayer * PAM module and login.c. It is needed because we can't really 51776339Snsayer * "converse" with the user, having already gone to the trouble of 51876339Snsayer * getting their username and password through an encrypted channel. 51976339Snsayer */ 52049887Snsayer 52176339Snsayer#define COPY_STRING(s) (s ? strdup(s):NULL) 52276339Snsayer 52376339Snsayerstruct cred_t { 52476339Snsayer const char *uname; 52576339Snsayer const char *pass; 52676339Snsayer}; 52776339Snsayertypedef struct cred_t cred_t; 52876339Snsayer 52976339Snsayerauth_conv(int num_msg, const struct pam_message **msg, 53076339Snsayer struct pam_response **resp, void *appdata) 53176339Snsayer{ 53276339Snsayer int i; 53376339Snsayer cred_t *cred = (cred_t *) appdata; 53476339Snsayer struct pam_response *reply = 53576339Snsayer malloc(sizeof(struct pam_response) * num_msg); 53676339Snsayer 53776339Snsayer for (i = 0; i < num_msg; i++) { 53876339Snsayer switch (msg[i]->msg_style) { 53976339Snsayer case PAM_PROMPT_ECHO_ON: /* assume want user name */ 54076339Snsayer reply[i].resp_retcode = PAM_SUCCESS; 54176339Snsayer reply[i].resp = COPY_STRING(cred->uname); 54276339Snsayer /* PAM frees resp. */ 54376339Snsayer break; 54476339Snsayer case PAM_PROMPT_ECHO_OFF: /* assume want password */ 54576339Snsayer reply[i].resp_retcode = PAM_SUCCESS; 54676339Snsayer reply[i].resp = COPY_STRING(cred->pass); 54776339Snsayer /* PAM frees resp. */ 54876339Snsayer break; 54976339Snsayer case PAM_TEXT_INFO: 55076339Snsayer case PAM_ERROR_MSG: 55176339Snsayer reply[i].resp_retcode = PAM_SUCCESS; 55276339Snsayer reply[i].resp = NULL; 55376339Snsayer break; 55476339Snsayer default: /* unknown message style */ 55576339Snsayer free(reply); 55676339Snsayer return PAM_CONV_ERR; 55776339Snsayer } 55876339Snsayer } 55976339Snsayer 56076339Snsayer *resp = reply; 56176339Snsayer return PAM_SUCCESS; 56276339Snsayer} 56376339Snsayer 56476339Snsayer/* 56576339Snsayer * The PAM version as a side effect may put a new username in *user. 56676339Snsayer */ 56776339Snsayerint check_user(const char *name, const char *pass) 56876339Snsayer{ 56976339Snsayer pam_handle_t *pamh = NULL; 57076339Snsayer const char *tmpl_user; 57176339Snsayer const void *item; 57276339Snsayer int rval; 57376339Snsayer int e; 57476339Snsayer cred_t auth_cred = { name, pass }; 57576339Snsayer struct pam_conv conv = { &auth_conv, &auth_cred }; 57676339Snsayer 57776339Snsayer e = pam_start("telnetd", name, &conv, &pamh); 57876339Snsayer if (e != PAM_SUCCESS) { 57976339Snsayer syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e)); 58076339Snsayer return 0; 58176339Snsayer } 58276339Snsayer 58376339Snsayer#if 0 /* Where can we find this value? */ 58476339Snsayer e = pam_set_item(pamh, PAM_RHOST, remotehost); 58576339Snsayer if (e != PAM_SUCCESS) { 58676339Snsayer syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s", 58776339Snsayer pam_strerror(pamh, e)); 58876339Snsayer return 0; 58976339Snsayer } 59049887Snsayer#endif 59149887Snsayer 59276339Snsayer e = pam_authenticate(pamh, 0); 59376339Snsayer switch (e) { 59476339Snsayer case PAM_SUCCESS: 59576339Snsayer /* 59676339Snsayer * With PAM we support the concept of a "template" 59776339Snsayer * user. The user enters a login name which is 59876339Snsayer * authenticated by PAM, usually via a remote service 59976339Snsayer * such as RADIUS or TACACS+. If authentication 60076339Snsayer * succeeds, a different but related "template" name 60176339Snsayer * is used for setting the credentials, shell, and 60276339Snsayer * home directory. The name the user enters need only 60376339Snsayer * exist on the remote authentication server, but the 60476339Snsayer * template name must be present in the local password 60576339Snsayer * database. 60676339Snsayer * 60776339Snsayer * This is supported by two various mechanisms in the 60876339Snsayer * individual modules. However, from the application's 60976339Snsayer * point of view, the template user is always passed 61076339Snsayer * back as a changed value of the PAM_USER item. 61176339Snsayer */ 61276339Snsayer if ((e = pam_get_item(pamh, PAM_USER, &item)) == 61376339Snsayer PAM_SUCCESS) { 61476339Snsayer strcpy(user, (const char *) item); 61576339Snsayer } else 61676339Snsayer syslog(LOG_ERR, "Couldn't get PAM_USER: %s", 61776339Snsayer pam_strerror(pamh, e)); 61876610Snsayer if (isroot(user) && !rootterm(line)) 61976610Snsayer rval = 0; 62076610Snsayer else 62176610Snsayer rval = 1; 62276339Snsayer break; 62376339Snsayer 62476339Snsayer case PAM_AUTH_ERR: 62576339Snsayer case PAM_USER_UNKNOWN: 62676339Snsayer case PAM_MAXTRIES: 62776339Snsayer rval = 0; 62876339Snsayer break; 62976339Snsayer 63076339Snsayer default: 63176339Snsayer syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e)); 63276339Snsayer rval = 0; 63376339Snsayer break; 63476339Snsayer } 63576339Snsayer 63676339Snsayer if ((e = pam_end(pamh, e)) != PAM_SUCCESS) { 63776339Snsayer syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); 63876339Snsayer rval = 0; 63976339Snsayer } 64076339Snsayer return rval; 64176339Snsayer} 64276339Snsayer 64376339Snsayer#endif 64476339Snsayer 64576339Snsayer#endif 64676339Snsayer 647