File: bif_gnw.c

package info (click to toggle)
virtuoso-opensource 6.1.6+dfsg2-4
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid, stretch
  • size: 260,992 kB
  • ctags: 125,220
  • sloc: ansic: 652,748; sql: 458,419; xml: 282,834; java: 61,031; sh: 40,031; cpp: 36,890; cs: 25,240; php: 12,692; yacc: 9,523; lex: 7,018; makefile: 6,157; jsp: 4,484; awk: 1,643; perl: 1,013; ruby: 1,003; python: 326
file content (278 lines) | stat: -rw-r--r-- 8,332 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/*
 *  bif_gnw.c
 *
 *  $Id$
 *
 *  GNW specific extensions
 *
 *  This file is part of the OpenLink Software Virtuoso Open-Source (VOS)
 *  project.
 *
 *  Copyright (C) 1998-2012 OpenLink Software
 *
 *  This project is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License as published by the
 *  Free Software Foundation; only version 2 of the License, dated June 1991.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#include "sqlnode.h"
#include "security.h"
#include "sqlbif.h"


static char *bif_aux_base64chars =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";


char *crypt (const char *pw, const char *salt);


/* The lowermost bits come to the end now. */
static char *
bif_aux_encode_n_sextets_to_base64 (unsigned long int x, int n_sextets, char *dest_space)
{
  int i = 0;

  /* E.g. if n_sextets is 2, then leave only twelve lower bits
   * (2**12 = 4096, octal 07777 = 4095)
   */
  x &= ((1 << (6 * n_sextets)) - 1);

#ifdef OTHER_WAY_WOULD_BE_LIKE_THIS	/* That we do not use now. */
  while (i < n_sextets)
    {
      dest_space[i++] = bif_aux_base64chars[(x & 077)];		/* Index between 0 and 63 */
      x >>= 6;			/* Shift off six lowermost bits. */
    }
#else
  i = n_sextets;
  while (i)
    {
      dest_space[--i] = bif_aux_base64chars[(x & 077)];		/* Index between 0 and 63 */
      x >>= 6;			/* Shift off six lowermost bits. */
    }
#endif

  dest_space[n_sextets] = '\0';	/* Add terminating zero. */

  return (dest_space);
}


/* Calls Unix's one-directional passwd crypt. See man crypt
 * This one can be furthermore called with the second arg salt
 * specified as integer (only twelve lowest bits are significant (0 4095)
 * which is then converted to the required [a-zA-Z0-9./]*2 salt string
 * with the above bif_aux_encode_n_sextets_to_base64 function.
 */

#ifdef UNIX
static caddr_t
bif_crypt (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
{
  caddr_t str_to_be_crypted = bif_string_or_null_arg (qst, args, 0, "crypt");
  caddr_t salt = bif_arg (qst, args, 1, "crypt");
  caddr_t res;
  dtp_t salt_type = DV_TYPE_OF (salt);
  char *salt_str, *crypt_result;
  char salt_space[10];

  if (NULL == str_to_be_crypted)
    {
      return (NEW_DB_NULL);
    }
  if (DV_DB_NULL == salt_type)
    {
      return (NEW_DB_NULL);
    }

  if (is_some_sort_of_a_string (salt_type))
    {
      salt_str = salt;
    }
  else if (is_some_sort_of_an_integer (salt_type))
    {
      long salt_n = unbox (salt);
      salt_str = bif_aux_encode_n_sextets_to_base64 (salt_n, 2, salt_space);
    }
  else /* if (NOT is_some_sort_of_a_string (salt_type)) */
    {
      sqlr_new_error ("21S01", "SR096",
	  "Function crypt needs a string or integer as its second argument."
	  " Not an arg of type %s (%d)",
	  dv_type_title (salt_type), salt_type);
      salt_str = ""; /* make cc happy */
    }

  /* We borrow here time_mtx for other purposes, because crypt returns
   * a pointer to static string.
   */
  mutex_enter (time_mtx);
  crypt_result = crypt (str_to_be_crypted, salt_str);
  res = box_dv_short_string (crypt_result);
  mutex_leave (time_mtx);
  return (res);

}
#endif /* UNIX for bif_crypt */




/* Like bif_date_string but generates the date string as seen in GMT zone. */
static caddr_t
bif_datestringGMT (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
{
  return (bif_date_string (qst, err_ret, args));
}


/*
 *  bif_decode_to_intvec  --  Coded by Antti Karttunen 8. August 1998
 *
 *  Takes three arguments: in in_string varchar,
 *                         in alphabet  varchar,
 *                         in out_width_in_bits integer
 *
 *  The first argument, in_string is the string of zero or more characters,
 *
 *  The second argument, alphabet, should be a string of 2^n (where n = 1 - 8),
 *  that is 2, 4, 8, 16, 32, 64, 128 or 256 distinct characters.
 *
 *  The in_string should contain only characters present in alphabet.
 *
 *  The third argument, out_width_in_bits is a number between 1 and 32,
 *  which specifies in how wide chunks the resulting bits should be stored
 *  into the resulting vector. If it is 1, then each element is an
 *  integer either 0 or 1, that is, a proper bit.
 *  If it is 8, then each element is a byte in range 0 - 255,
 *  and if it is 16, then they are words in range 0 - 65535,
 *  and with maximum. 32 they are longwords in range 0 - 4294967295
 *
 *  The alphabet is usually something like static char *bif_aux_base64chars
 *  presented in this module
 *  (i.e. 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./')
 *  that is appropriate for decoding uuencoded and encrypted strings,
 *  where each encoded character presents six bits. (log2(64) = 6)
 *
 */
static caddr_t
bif_decode_to_intvec (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
{
  caddr_t in_string = bif_string_or_null_arg (qst, args, 0, "decode_to_intvec");
  caddr_t alphabet = bif_string_arg (qst, args, 1, "decode_to_intvec");
  long out_width_in_bits = bif_long_arg (qst, args, 2, "decode_to_intvec");
  caddr_t vec;			/* The resulting vector of integers. */
  int orig_alphalen, alphalen, in_width_in_bits, string_len;
  int bits_total, vec_len;
  int i, j, k, l;
  unsigned int in_bits, high_bit_mask;
  unsigned long int out_bits;

  orig_alphalen = alphalen = box_length (alphabet) - 1;
  in_width_in_bits = 0;

  if (alphalen < 2)
    {
      goto invalid_alphabet;
    }

  while (0 == (alphalen & 1))	/* Shift as long as bit-0 stays zero. */
    {
      alphalen >>= 1;		/* Shift right once. */
      in_width_in_bits++;
    }

  if (alphalen > 1)		/* There are more than one 1-bits present in alphalen? */
    {
    invalid_alphabet:
      sqlr_new_error ("21S01", "GN001",
	  "Function decode_to_intvec needs an alphabet string of length 2, 4, 8, 16, 32, 64, 128 or 256 as its second argument "
	  "not a string of length %d", orig_alphalen);
    }

  if ((out_width_in_bits < 1) || (out_width_in_bits > 32))
    {
      sqlr_new_error ("21S01", "GN002",
	  "Function decode_to_intvec needs as its third argument "
	  "an integer between 1 - 32");
    }

  if (NULL == in_string)
    {
      return (NEW_DB_NULL);
    }
  string_len = box_length (in_string) - 1;

  bits_total = (string_len * in_width_in_bits);

  vec_len = bits_total / out_width_in_bits;
  if (bits_total % out_width_in_bits)	/* If does not divide exactly, */
    {
      vec_len++;
    }				/* then add one to result vec's length. */

  vec = dk_alloc_box ((vec_len * sizeof (ptrlong)), DV_ARRAY_OF_LONG);

  i = j = 0;
  high_bit_mask = (1 << (in_width_in_bits - 1));
  /* 1 -> 1, 2 -> 2, 3 -> 4, 4 -> 8, 5 -> 16, 6 -> 32, 7 -> 64, 8 -> 128 */
  out_bits = l = 0;

  while (i < string_len)
    {
      char *ptr_to_string = strchr (alphabet, ((unsigned char *) in_string)[i++]);

      if (ptr_to_string)
	{
	  in_bits = (ptr_to_string - alphabet);
	}
      else
	{
	  in_bits = 0;
	}			/* The letter was not found from alphabet */

      /* This order is used now, from bit-(in_width_in_bits-1) to bit-0. */
      for (k = 0; (k < in_width_in_bits); k++, in_bits <<= 1, out_bits <<= 1)
	{
	  out_bits |= ((in_bits & high_bit_mask) ? 1 : 0);
	  if (++l == out_width_in_bits)
	    {
	      ((ptrlong *) vec)[j++] = out_bits;
	      out_bits = l = 0;
	    }
	}
    }

  /* If there are still some bits to output?
   * I.e. the remainder (bits_total%out_width_in_bits) is not zero.
   * then put the last batch of out_bits as the last element of the output vector
   */
  if (l != 0)
    {
      ((ptrlong *) vec)[j] = out_bits;
    }

  return (vec);			/* Return the resulting vector. */
}

void
bif_gnw_init (void)
{
  bif_define_typed ("datestringGMT", bif_datestringGMT, & bt_varchar);
  bif_define_typed ("decode_to_intvec", bif_decode_to_intvec, & bt_any);

#ifdef UNIX
  bif_define_typed ("unix_crypt", bif_crypt, & bt_varchar);
#endif
}