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