154359Sroberto/*- 254359Sroberto * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il> 354359Sroberto * All rights reserved. 454359Sroberto * 554359Sroberto * Redistribution and use in source and binary forms, with or without 654359Sroberto * modification, are permitted provided that the following conditions 754359Sroberto * are met: 854359Sroberto * 1. Redistributions of source code must retain the above copyright 954359Sroberto * notice, this list of conditions and the following disclaimer. 1054359Sroberto * 2. Redistributions in binary form must reproduce the above copyright 1154359Sroberto * notice, this list of conditions and the following disclaimer in the 1254359Sroberto * documentation and/or other materials provided with the distribution. 1354359Sroberto * 1454359Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1554359Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1654359Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1754359Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1854359Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1954359Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2054359Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2154359Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2254359Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2354359Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2454359Sroberto * SUCH DAMAGE. 2554359Sroberto * 2654359Sroberto */ 2754359Sroberto 2854359Sroberto/* 2954359Sroberto | $Id: auth_subr.c,v 2.2 2007/06/01 08:09:37 danny Exp $ 3054359Sroberto */ 3154359Sroberto 3254359Sroberto#include <sys/cdefs.h> 3354359Sroberto__FBSDID("$FreeBSD$"); 3454359Sroberto 3554359Sroberto#include <sys/param.h> 3654359Sroberto#include <sys/types.h> 3754359Sroberto#include <sys/socket.h> 3854359Sroberto#include <sys/sysctl.h> 3954359Sroberto 4054359Sroberto#include <netinet/in.h> 4154359Sroberto#include <netinet/tcp.h> 4254359Sroberto#include <arpa/inet.h> 4354359Sroberto#include <unistd.h> 4454359Sroberto#include <stdlib.h> 4554359Sroberto#include <stdio.h> 4654359Sroberto#include <string.h> 4754359Sroberto#include <fcntl.h> 4854359Sroberto 4954359Sroberto#include <md5.h> 5054359Sroberto#include <sha.h> 5154359Sroberto 5254359Sroberto#include <dev/iscsi/initiator/iscsi.h> 5354359Sroberto#include "iscontrol.h" 5454359Sroberto 5554359Srobertostatic int 5654359SrobertochapMD5(char id, char *cp, char *chapSecret, unsigned char *digest) 5754359Sroberto{ 5854359Sroberto MD5_CTX ctx; 5954359Sroberto char *tmp; 6054359Sroberto int len; 6154359Sroberto 62285612Sdelphij debug_called(3); 6382498Sroberto 6454359Sroberto MD5Init(&ctx); 65285612Sdelphij 66106163Sroberto MD5Update(&ctx, &id, 1); 67285612Sdelphij 68285612Sdelphij if((len = str2bin(chapSecret, &tmp)) == 0) { 69285612Sdelphij // print error 70285612Sdelphij return -1; 7154359Sroberto } 7254359Sroberto MD5Update(&ctx, tmp, len); 7354359Sroberto free(tmp); 7454359Sroberto 7554359Sroberto if((len = str2bin(cp, &tmp)) == 0) { 7654359Sroberto // print error 7754359Sroberto return -1; 7854359Sroberto } 7954359Sroberto MD5Update(&ctx, tmp, len); 8054359Sroberto free(tmp); 8154359Sroberto 8254359Sroberto MD5Final(digest, &ctx); 8354359Sroberto 8454359Sroberto 8554359Sroberto return 0; 8654359Sroberto} 8754359Sroberto 8854359Srobertostatic int 8954359SrobertochapSHA1(char id, char *cp, char *chapSecret, unsigned char *digest) 9054359Sroberto{ 9154359Sroberto SHA1_CTX ctx; 9254359Sroberto char *tmp; 9354359Sroberto int len; 9454359Sroberto 9554359Sroberto debug_called(3); 9654359Sroberto 9754359Sroberto SHA1_Init(&ctx); 9854359Sroberto 9954359Sroberto SHA1_Update(&ctx, &id, 1); 10054359Sroberto 10154359Sroberto if((len = str2bin(chapSecret, &tmp)) == 0) { 10254359Sroberto // print error 10354359Sroberto return -1; 10454359Sroberto } 10554359Sroberto SHA1_Update(&ctx, tmp, len); 10654359Sroberto free(tmp); 10754359Sroberto 10854359Sroberto if((len = str2bin(cp, &tmp)) == 0) { 10954359Sroberto // print error 11054359Sroberto return -1; 11154359Sroberto } 11254359Sroberto SHA1_Update(&ctx, tmp, len); 11354359Sroberto free(tmp); 11454359Sroberto 11554359Sroberto SHA1_Final(digest, &ctx); 11654359Sroberto 11754359Sroberto return 0; 11854359Sroberto 11954359Sroberto} 12054359Sroberto/* 12154359Sroberto | the input text format can be anything that the rfc3270 defines 12254359Sroberto | (see section 5.1 and str2bin) 12354359Sroberto | digest length for md5 is 128bits, and for sha1 is 160bits. 12454359Sroberto | digest is an ASCII string which represents the bits in 12554359Sroberto | hexadecimal or base64 according to the challenge(cp) format 12654359Sroberto */ 12754359Srobertochar * 12854359SrobertochapDigest(char *ap, char id, char *cp, char *chapSecret) 12954359Sroberto{ 13054359Sroberto int len; 13154359Sroberto unsigned char digest[20]; 13254359Sroberto char encoding[3]; 13354359Sroberto 13454359Sroberto debug_called(3); 13554359Sroberto 13654359Sroberto len = 0; 13754359Sroberto if(strcmp(ap, "5") == 0 && chapMD5(id, cp, chapSecret, digest) == 0) 13854359Sroberto len = 16; 13954359Sroberto else 14054359Sroberto if(strcmp(ap, "7") == 0 && chapSHA1(id, cp, chapSecret, digest) == 0) 14154359Sroberto len = 20; 14254359Sroberto 14354359Sroberto if(len) { 14454359Sroberto sprintf(encoding, "%.2s", cp); 14554359Sroberto return bin2str(encoding, digest, len); 14654359Sroberto } 14754359Sroberto 14854359Sroberto return NULL; 14954359Sroberto} 15054359Sroberto 15154359Srobertochar * 15254359SrobertogenChapChallenge(char *encoding, uint len) 15354359Sroberto{ 15454359Sroberto int fd; 15554359Sroberto unsigned char tmp[1024]; 15654359Sroberto 15754359Sroberto if(len > sizeof(tmp)) 15854359Sroberto return NULL; 15954359Sroberto 16054359Sroberto if((fd = open("/dev/random", O_RDONLY)) != -1) { 16154359Sroberto read(fd, tmp, len); 16254359Sroberto close(fd); 16354359Sroberto return bin2str(encoding, tmp, len); 16454359Sroberto } 16554359Sroberto perror("/dev/random"); 16654359Sroberto // make up something ... 16754359Sroberto return NULL; 16854359Sroberto} 16954359Sroberto 17054359Sroberto#ifdef TEST_AUTH 17154359Srobertostatic void 17254359Srobertopuke(char *str, unsigned char *dg, int len) 17354359Sroberto{ 17454359Sroberto printf("%3d] %s\n 0x", len, str); 17554359Sroberto while(len-- > 0) 17654359Sroberto printf("%02x", *dg++); 17754359Sroberto printf("\n"); 17854359Sroberto} 17954359Sroberto 18054359Srobertomain(int cc, char **vv) 18154359Sroberto{ 18254359Sroberto char *p, *ap, *ip, *cp, *chapSecret, *digest; 18354359Sroberto int len; 184132451Sroberto 185132451Sroberto#if 0 18654359Sroberto ap = "5"; 18754359Sroberto chapSecret = "0xa5aff013dd839b1edd31ee73a1df0b1b"; 18854359Sroberto// chapSecret = "abcdefghijklmnop"; 18954359Sroberto len = str2bin(chapSecret, &cp); 19054359Sroberto puke(chapSecret, cp, len); 19154359Sroberto 19254359Sroberto ip = "238"; 19354359Sroberto cp = "0xbd456029"; 19454359Sroberto 19554359Sroberto 19654359Sroberto if((digest = chapDigest(ap, ip, cp, chapSecret)) != NULL) { 19754359Sroberto len = str2bin(digest, &cp); 19854359Sroberto puke(digest, cp, len); 19954359Sroberto } 20054359Sroberto#else 20154359Sroberto printf("%d] %s\n", 24, genChallenge("0X", 24)); 20254359Sroberto#endif 20354359Sroberto} 20454359Sroberto#endif 20554359Sroberto