1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30/*
31 | $Id: misc.c,v 2.1 2006/11/12 08:06:51 danny Exp $
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: stable/11/sbin/iscontrol/misc.c 330449 2018-03-05 07:26:05Z eadler $");
36
37#include <sys/param.h>
38#include <sys/types.h>
39#include <sys/socket.h>
40#include <sys/sysctl.h>
41
42#include <netinet/in.h>
43#include <netinet/tcp.h>
44#include <arpa/inet.h>
45#include <stdlib.h>
46#include <stdio.h>
47#include <string.h>
48
49#include <dev/iscsi_initiator/iscsi.h>
50#include "iscontrol.h"
51
52static inline char
53c2b(unsigned char c)
54{
55     switch(c) {
56     case '0' ... '9':
57	  return c - '0';
58     case 'a' ... 'f':
59	  return c - 'a' + 10;
60     case 'A' ... 'F':
61	  return c - 'A' + 10;
62     }
63     return 0;
64}
65
66static char 	base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
67	                   "abcdefghijklmnopqrstuvwxyz"
68	                   "0123456789+/";
69
70static __inline unsigned char
71c64tobin(unsigned char c64)
72{
73     int	i;
74     for(i = 0; i < 64; i++)
75	  if(base64[i] == c64)
76	       break;
77     return i;
78}
79/*
80 | according to rfc3720, the binary string
81 | cannot be larger than 1024 - but i can't find it :-) XXX
82 | not enforced yet.
83 */
84int
85str2bin(char *str, char **rsp)
86{
87     char	*src, *dst, *tmp;
88     int	i, len = 0;
89
90     src = str;
91     tmp = NULL;
92     if(strncasecmp("0x", src, 2) == 0) {
93	  src += 2;
94	  len = strlen(src);
95
96	  if((tmp = malloc((len+1)/2)) == NULL) {
97	       // XXX: print some error?
98	       return 0;
99	  }
100	  dst = tmp;
101	  if(len & 1)
102	       *dst++ = c2b(*src++);
103	  while(*src) {
104	       *dst = c2b(*src++) << 4;
105	       *dst++ |= c2b(*src++);
106	  }
107	  len = dst - tmp;
108     } else
109     if(strncasecmp("0b", src , 2) == 0) {
110	  // base64
111	  unsigned char b6;
112
113	  src += 2;
114	  len = strlen(src) / 4 * 3;
115	  if((tmp = malloc(len)) == NULL) {
116	       // XXX: print some error?
117	       return 0;
118	  }
119	  dst = tmp;
120	  i = 0;
121	  while(*src && ((b6 = c64tobin(*src++)) != 64)) {
122	       switch(i % 4) {
123	       case 0:
124		    *dst = b6 << 2;
125		    break;
126	       case 1:
127		    *dst++ |= b6 >> 4;
128		    *dst = b6 << 4;
129		    break;
130	       case 2:
131		    *dst++ |= b6 >> 2;
132		    *dst = b6 << 6;
133		    break;
134	       case 3:
135		    *dst++ |= b6;
136		    break;
137	       }
138	       i++;
139	  }
140	  len = dst - tmp;
141     }
142     else {
143	  /*
144	   | assume it to be an ascii string, so just copy it
145	   */
146	  len = strlen(str);
147	  if((tmp = malloc(len)) == NULL)
148	       return 0;
149	  dst = tmp;
150	  src = str;
151	  while(*src)
152	       *dst++ = *src++;
153     }
154
155     *rsp = tmp;
156     return len;
157}
158
159char *
160bin2str(char *encoding, unsigned char *md, int blen)
161{
162     int	len;
163     char	*dst, *ds;
164     unsigned char *cp;
165
166     if(strncasecmp(encoding, "0x", 2) == 0) {
167	  char	ofmt[5];
168
169	  len = blen * 2;
170	  dst = malloc(len + 3);
171	  strcpy(dst, encoding);
172	  ds = dst + 2;
173	  cp = md;
174	  sprintf(ofmt, "%%02%c", encoding[1]);
175	  while(blen-- > 0) {
176	       sprintf(ds, ofmt, *cp++);
177	       ds += 2;
178	  }
179	  *ds = 0;
180	  return dst;
181     }
182     if(strncasecmp(encoding, "0b", 2) == 0) {
183	  int i, b6;
184
185	  len = (blen + 2) * 4 / 3;
186	  dst = malloc(len + 3);
187	  strcpy(dst, encoding);
188	  ds = dst + 2;
189	  cp = md;
190	  b6 = 0; // to keep compiler happy.
191	  for(i = 0; i < blen; i++) {
192	       switch(i % 3) {
193	       case 0:
194		    *ds++ = base64[*cp >> 2];
195		    b6 = (*cp & 0x3) << 4;
196		    break;
197	       case 1:
198		    b6 += (*cp >> 4);
199		    *ds++ = base64[b6];
200		    b6 = (*cp & 0xf) << 2;
201		    break;
202	       case 2:
203		    b6 += (*cp >> 6);
204		    *ds++ = base64[b6];
205		    *ds++ = base64[*cp & 0x3f];
206	       }
207	       cp++;
208	  }
209	  switch(blen % 3) {
210	  case 0:
211	       break;
212	  case 1:
213	       *ds++ = base64[b6];
214	       *ds++ = '=';
215	       *ds++ = '=';
216	       break;
217	  case 2:
218	       *ds++ = base64[b6];
219	       *ds++ = '=';
220	       break;
221	  }
222
223	  *ds = 0;
224	  return dst;
225     }
226
227     return NULL;
228}
229