Path: blob/main/crypto/heimdal/appl/telnet/libtelnet/rsaencpwd.c
34879 views
/*-1* Copyright (c) 1992, 19932* The Regents of the University of California. All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12* 3. All advertising materials mentioning features or use of this software13* must display the following acknowledgement:14* This product includes software developed by the University of15* California, Berkeley and its contributors.16* 4. Neither the name of the University nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233#include <config.h>3435RCSID("$Id$");3637#ifdef RSA_ENCPWD38/*39* COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION40* ALL RIGHTS RESERVED41*42* "Digital Equipment Corporation authorizes the reproduction,43* distribution and modification of this software subject to the following44* restrictions:45*46* 1. Any partial or whole copy of this software, or any modification47* thereof, must include this copyright notice in its entirety.48*49* 2. This software is supplied "as is" with no warranty of any kind,50* expressed or implied, for any purpose, including any warranty of fitness51* or merchantibility. DIGITAL assumes no responsibility for the use or52* reliability of this software, nor promises to provide any form of53* support for it on any basis.54*55* 3. Distribution of this software is authorized only if no profit or56* remuneration of any kind is received in exchange for such distribution.57*58* 4. This software produces public key authentication certificates59* bearing an expiration date established by DIGITAL and RSA Data60* Security, Inc. It may cease to generate certificates after the expiration61* date. Any modification of this software that changes or defeats62* the expiration date or its effect is unauthorized.63*64* 5. Software that will renew or extend the expiration date of65* authentication certificates produced by this software may be obtained66* from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA67* 94065, (415)595-8782, or from DIGITAL"68*69*/7071#include <sys/types.h>72#ifdef HAVE_ARPA_TELNET_H73#include <arpa/telnet.h>74#endif75#include <pwd.h>76#include <stdio.h>7778#include <stdlib.h>79#include <string.h>80#ifdef SOCKS81#include <socks.h>82#endif8384#include "encrypt.h"85#include "auth.h"86#include "misc.h"87#include "cdc.h"8889extern auth_debug_mode;9091static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,92AUTHTYPE_RSA_ENCPWD, };93static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,94TELQUAL_NAME, };9596#define RSA_ENCPWD_AUTH 0 /* Authentication data follows */97#define RSA_ENCPWD_REJECT 1 /* Rejected (reason might follow) */98#define RSA_ENCPWD_ACCEPT 2 /* Accepted */99#define RSA_ENCPWD_CHALLENGEKEY 3 /* Challenge and public key */100101#define NAME_SZ 40102#define CHAL_SZ 20103#define PWD_SZ 40104105static KTEXT_ST auth;106static char name[NAME_SZ];107static char user_passwd[PWD_SZ];108static char key_file[2*NAME_SZ];109static char lhostname[NAME_SZ];110static char challenge[CHAL_SZ];111static int challenge_len;112113static int114Data(ap, type, d, c)115Authenticator *ap;116int type;117void *d;118int c;119{120unsigned char *p = str_data + 4;121unsigned char *cd = (unsigned char *)d;122123if (c == -1)124c = strlen((char *)cd);125126if (0) {127printf("%s:%d: [%d] (%d)",128str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",129str_data[3],130type, c);131printd(d, c);132printf("\r\n");133}134*p++ = ap->type;135*p++ = ap->way;136if (type != NULL) *p++ = type;137while (c-- > 0) {138if ((*p++ = *cd++) == IAC)139*p++ = IAC;140}141*p++ = IAC;142*p++ = SE;143if (str_data[3] == TELQUAL_IS)144printsub('>', &str_data[2], p - (&str_data[2]));145return(telnet_net_write(str_data, p - str_data));146}147148int149rsaencpwd_init(ap, server)150Authenticator *ap;151int server;152{153char *cp;154FILE *fp;155156if (server) {157str_data[3] = TELQUAL_REPLY;158memset(key_file, 0, sizeof(key_file));159gethostname(lhostname, sizeof(lhostname));160if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0';161snprintf(key_file, sizeof(key_file),162SYSCONFDIR "/.%s_privkey", lhostname);163if ((fp=fopen(key_file, "r"))==NULL) return(0);164fclose(fp);165} else {166str_data[3] = TELQUAL_IS;167}168return(1);169}170171int172rsaencpwd_send(ap)173Authenticator *ap;174{175176printf("[ Trying RSAENCPWD ... ]\r\n");177if (!UserNameRequested) {178return(0);179}180if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {181return(0);182}183if (!Data(ap, NULL, NULL, 0)) {184return(0);185}186187188return(1);189}190191void192rsaencpwd_is(ap, data, cnt)193Authenticator *ap;194unsigned char *data;195int cnt;196{197Session_Key skey;198des_cblock datablock;199char r_passwd[PWD_SZ], r_user[NAME_SZ];200char *cp, key[160];201char chalkey[160], *ptr;202FILE *fp;203int r, i, j, chalkey_len, len;204time_t now;205206cnt--;207switch (*data++) {208case RSA_ENCPWD_AUTH:209memmove(auth.dat, data, auth.length = cnt);210211if ((fp=fopen(key_file, "r"))==NULL) {212Data(ap, RSA_ENCPWD_REJECT, "Auth failed", -1);213auth_finished(ap, AUTH_REJECT);214return;215}216/*217* get privkey218*/219fscanf(fp, "%x;", &len);220for (i=0;i<len;i++) {221j = getc(fp); key[i]=j;222}223fclose(fp);224225r = accept_rsa_encpwd(&auth, key, challenge,226challenge_len, r_passwd);227if (r < 0) {228Data(ap, RSA_ENCPWD_REJECT, "Auth failed", -1);229auth_finished(ap, AUTH_REJECT);230return;231}232auth_encrypt_userpwd(r_passwd);233if (rsaencpwd_passwdok(UserNameRequested, UserPassword) == 0) {234/*235* illegal username and password236*/237Data(ap, RSA_ENCPWD_REJECT, "Illegal password", -1);238auth_finished(ap, AUTH_REJECT);239return;240}241242Data(ap, RSA_ENCPWD_ACCEPT, 0, 0);243auth_finished(ap, AUTH_USER);244break;245246247case IAC:248249/*250* If we are doing mutual authentication, get set up to send251* the challenge, and verify it when the response comes back.252*/253if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {254int i;255256257time(&now);258if ((now % 2) == 0) {259snprintf(challenge, sizeof(challenge), "%x", now);260challenge_len = strlen(challenge);261} else {262strlcpy(challenge, "randchal", sizeof(challenge));263challenge_len = 8;264}265266if ((fp=fopen(key_file, "r"))==NULL) {267Data(ap, RSA_ENCPWD_REJECT, "Auth failed", -1);268auth_finished(ap, AUTH_REJECT);269return;270}271/*272* skip privkey273*/274fscanf(fp, "%x;", &len);275for (i=0;i<len;i++) {276j = getc(fp);277}278/*279* get pubkey280*/281fscanf(fp, "%x;", &len);282for (i=0;i<len;i++) {283j = getc(fp); key[i]=j;284}285fclose(fp);286chalkey[0] = 0x30;287ptr = (char *) &chalkey[1];288chalkey_len = 1+NumEncodeLengthOctets(i)+i+1+NumEncodeLengthOctets(challenge_len)+challenge_len;289EncodeLength(ptr, chalkey_len);290ptr +=NumEncodeLengthOctets(chalkey_len);291*ptr++ = 0x04; /* OCTET STRING */292*ptr++ = challenge_len;293memmove(ptr, challenge, challenge_len);294ptr += challenge_len;295*ptr++ = 0x04; /* OCTET STRING */296EncodeLength(ptr, i);297ptr += NumEncodeLengthOctets(i);298memmove(ptr, key, i);299chalkey_len = 1+NumEncodeLengthOctets(chalkey_len)+chalkey_len;300Data(ap, RSA_ENCPWD_CHALLENGEKEY, chalkey, chalkey_len);301}302break;303304default:305Data(ap, RSA_ENCPWD_REJECT, 0, 0);306break;307}308}309310311void312rsaencpwd_reply(ap, data, cnt)313Authenticator *ap;314unsigned char *data;315int cnt;316{317Session_Key skey;318KTEXT_ST token;319des_cblock enckey;320int r, pubkey_len;321char randchal[CHAL_SZ], *cp;322char chalkey[160], pubkey[128], *ptr;323324if (cnt-- < 1)325return;326switch (*data++) {327case RSA_ENCPWD_REJECT:328if (cnt > 0) {329printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n",330cnt, data);331} else332printf("[ RSA_ENCPWD refuses authentication ]\r\n");333auth_send_retry();334return;335case RSA_ENCPWD_ACCEPT:336printf("[ RSA_ENCPWD accepts you ]\r\n");337auth_finished(ap, AUTH_USER);338return;339case RSA_ENCPWD_CHALLENGEKEY:340/*341* Verify that the response to the challenge is correct.342*/343344memmove(chalkey, data, cnt);345ptr = (char *) &chalkey[0];346ptr += DecodeHeaderLength(chalkey);347if (*ptr != 0x04) {348return;349}350*ptr++;351challenge_len = DecodeValueLength(ptr);352ptr += NumEncodeLengthOctets(challenge_len);353memmove(challenge, ptr, challenge_len);354ptr += challenge_len;355if (*ptr != 0x04) {356return;357}358*ptr++;359pubkey_len = DecodeValueLength(ptr);360ptr += NumEncodeLengthOctets(pubkey_len);361memmove(pubkey, ptr, pubkey_len);362memset(user_passwd, 0, sizeof(user_passwd));363des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);364UserPassword = user_passwd;365Challenge = challenge;366r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey);367if (r < 0) {368token.length = 1;369}370371if (!Data(ap, RSA_ENCPWD_AUTH, token.dat, token.length)) {372return;373}374375break;376377default:378return;379}380}381382int383rsaencpwd_status(ap, name, name_sz, level)384Authenticator *ap;385char *name;386size_t name_sz;387int level;388{389390if (level < AUTH_USER)391return(level);392393if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) {394strlcpy(name, UserNameRequested, name_sz);395return(AUTH_VALID);396} else {397return(AUTH_USER);398}399}400401#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}402#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}403404void405rsaencpwd_printsub(unsigned char *data, size_t cnt,406unsigned char * buf, size_t buflen)407{408size_t i;409410buf[buflen-1] = '\0'; /* make sure it's NULL terminated */411buflen -= 1;412413switch(data[3]) {414case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */415strlcpy((char *)buf, " REJECT ", buflen);416goto common;417418case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */419strlcpy((char *)buf, " ACCEPT ", buflen);420common:421BUMP(buf, buflen);422if (cnt <= 4)423break;424ADDC(buf, buflen, '"');425for (i = 4; i < cnt; i++)426ADDC(buf, buflen, data[i]);427ADDC(buf, buflen, '"');428ADDC(buf, buflen, '\0');429break;430431case RSA_ENCPWD_AUTH: /* Authentication data follows */432strlcpy((char *)buf, " AUTH", buflen);433goto common2;434435case RSA_ENCPWD_CHALLENGEKEY:436strlcpy((char *)buf, " CHALLENGEKEY", buflen);437goto common2;438439default:440snprintf(buf, buflen, " %d (unknown)", data[3]);441common2:442BUMP(buf, buflen);443for (i = 4; i < cnt; i++) {444snprintf(buf, buflen, " %d", data[i]);445BUMP(buf, buflen);446}447break;448}449}450451int rsaencpwd_passwdok(name, passwd)452char *name, *passwd;453{454char *crypt();455char *salt, *p;456struct passwd *pwd;457int passwdok_status = 0;458459if (pwd = k_getpwnam(name))460salt = pwd->pw_passwd;461else salt = "xx";462463p = crypt(passwd, salt);464465if (pwd && !strcmp(p, pwd->pw_passwd)) {466passwdok_status = 1;467} else passwdok_status = 0;468return(passwdok_status);469}470471#endif472473#ifdef notdef474475prkey(msg, key)476char *msg;477unsigned char *key;478{479int i;480printf("%s:", msg);481for (i = 0; i < 8; i++)482printf(" %3d", key[i]);483printf("\r\n");484}485#endif486487488