gsasl  1.10.0
About: GNU SASL is an implementation of the Simple Authentication and Security Layer (SASL). Development version.
  Fossies Dox: gsasl-1.10.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

gss-extra.c
Go to the documentation of this file.
1 /* gss-extra.c --- Provide GSS-API symbols when missing from library.
2  * Copyright (C) 2010-2021 Simon Josefsson
3  *
4  * This file is part of GNU SASL Library.
5  *
6  * GNU SASL Library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * as published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * GNU SASL Library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with GNU SASL Library; if not, write to the Free
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26 
27 /* Get specification. */
28 #include "gss-extra.h"
29 
30 /* Get strcmp. */
31 #include <string.h>
32 
33 /* Get malloc, free. */
34 #include <stdlib.h>
35 
36 #ifndef HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE
37 /* MIT Kerberos for Windows version 3.2.2 lacks this. */
38 static gss_OID_desc tmp = {
39  10,
40  (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"
41 };
43 
44 #endif
45 
46 #ifndef HAVE_GSS_OID_EQUAL
47 
48 int
49 gss_oid_equal (const gss_OID first_oid, const gss_OID second_oid)
50 {
51  return first_oid && second_oid &&
52  first_oid->length == second_oid->length &&
53  memcmp (first_oid->elements, second_oid->elements,
54  second_oid->length) == 0;
55 }
56 
57 #endif
58 
59 #ifndef HAVE_GSS_INQUIRE_MECH_FOR_SASLNAME
60 
61 /* Provide a dummy replacement function for GSS-API libraries that
62  lacks gss_inquire_mech_for_saslname. This function only works for
63  Kerberos V5. */
64 
65 OM_uint32
66 gss_inquire_mech_for_saslname (OM_uint32 * minor_status,
67  const gss_buffer_t sasl_mech_name,
68  gss_OID * mech_type)
69 {
70  static gss_OID_desc krb5oid_static = {
71  9, (char *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
72  };
73 
74  if (sasl_mech_name->value == NULL ||
75  sasl_mech_name->length != 8 ||
76  memcmp (sasl_mech_name->value, "GS2-KRB5", 8) != 0)
77  {
78  if (minor_status)
79  *minor_status = 0;
80  return GSS_S_BAD_MECH;
81  }
82 
83  if (mech_type)
84  *mech_type = &krb5oid_static;
85 
86  return GSS_S_COMPLETE;
87 }
88 
89 #endif
90 
91 /*
92  * The functions _gss_asn1_length_der and _gss_asn1_get_length_der are
93  * borrowed from GNU Libtasn1, under LGPLv2.1+.
94  * Copyright (C) 2002 Fabio Fiorina.
95  * The remaining functions below are copied from GNU GSS but re-licensed
96  * to LGPLv2.1+.
97  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Simon Josefsson
98  */
99 
100 #ifndef HAVE_GSS_ENCAPSULATE_TOKEN
101 
102 static void
103 _gss_asn1_length_der (size_t len, unsigned char *ans, size_t * ans_len)
104 {
105  size_t k;
106  unsigned char temp[sizeof (len)];
107 
108  if (len < 128)
109  {
110  if (ans != NULL)
111  ans[0] = (unsigned char) len;
112  *ans_len = 1;
113  }
114  else
115  {
116  k = 0;
117 
118  while (len)
119  {
120  temp[k++] = len & 0xFF;
121  len = len >> 8;
122  }
123 
124  *ans_len = k + 1;
125 
126  if (ans != NULL)
127  {
128  ans[0] = ((unsigned char) k & 0x7F) + 128;
129  while (k--)
130  ans[*ans_len - 1 - k] = temp[k];
131  }
132  }
133 }
134 
135 static OM_uint32
136 _gss_encapsulate_token_prefix (const char *prefix, size_t prefixlen,
137  const char *in, size_t inlen,
138  const char *oid, OM_uint32 oidlen,
139  void **out, size_t * outlen)
140 {
141  size_t oidlenlen;
142  size_t asn1len, asn1lenlen;
143  unsigned char *p;
144 
145  if (prefix == NULL)
146  prefixlen = 0;
147 
148  _gss_asn1_length_der (oidlen, NULL, &oidlenlen);
149  asn1len = 1 + oidlenlen + oidlen + prefixlen + inlen;
150  _gss_asn1_length_der (asn1len, NULL, &asn1lenlen);
151 
152  *outlen = 1 + asn1lenlen + asn1len;
153  p = *out = malloc (*outlen);
154  if (!p)
155  return -1;
156 
157  *p++ = '\x60';
158  _gss_asn1_length_der (asn1len, p, &asn1lenlen);
159  p += asn1lenlen;
160  *p++ = '\x06';
161  _gss_asn1_length_der (oidlen, p, &oidlenlen);
162  p += oidlenlen;
163  memcpy (p, oid, oidlen);
164  p += oidlen;
165  if (prefixlen > 0)
166  {
167  memcpy (p, prefix, prefixlen);
168  p += prefixlen;
169  }
170  memcpy (p, in, inlen);
171 
172  return 0;
173 }
174 
175 extern OM_uint32
176 gss_encapsulate_token (const gss_buffer_t input_token,
177  const gss_OID token_oid, gss_buffer_t output_token)
178 {
179  int rc;
180 
181  if (!input_token)
182  return GSS_S_CALL_INACCESSIBLE_READ;
183  if (!token_oid)
184  return GSS_S_CALL_INACCESSIBLE_READ;
185  if (!output_token)
186  return GSS_S_CALL_INACCESSIBLE_WRITE;
187 
189  input_token->value,
190  input_token->length,
191  token_oid->elements,
192  token_oid->length,
193  &output_token->value,
194  &output_token->length);
195  if (rc != 0)
196  return GSS_S_FAILURE;
197 
198  return GSS_S_COMPLETE;
199 }
200 
201 #endif /* HAVE_GSS_ENCAPSULATE_TOKEN */
202 
203 #ifndef HAVE_GSS_ENCAPSULATE_TOKEN
204 
205 static size_t
206 _gss_asn1_get_length_der (const char *der, size_t der_len, size_t * len)
207 {
208  size_t ans;
209  size_t k, punt;
210 
211  *len = 0;
212  if (der_len <= 0)
213  return 0;
214 
215  if (!(der[0] & 128))
216  {
217  /* short form */
218  *len = 1;
219  return (unsigned char) der[0];
220  }
221  else
222  {
223  /* Long form */
224  k = (unsigned char) der[0] & 0x7F;
225  punt = 1;
226  if (k)
227  { /* definite length method */
228  ans = 0;
229  while (punt <= k && punt < der_len)
230  {
231  size_t last = ans;
232 
233  ans = ans * 256 + (unsigned char) der[punt++];
234  if (ans < last)
235  /* we wrapped around, no bignum support... */
236  return -2;
237  }
238  }
239  else
240  { /* indefinite length method */
241  ans = -1;
242  }
243 
244  *len = punt;
245  return ans;
246  }
247 }
248 
249 static int
250 _gss_decapsulate_token (const char *in, size_t inlen,
251  char **oid, size_t * oidlen,
252  char **out, size_t * outlen)
253 {
254  size_t i;
255  size_t asn1lenlen;
256 
257  if (inlen-- == 0)
258  return -1;
259  if (*in++ != '\x60')
260  return -1;
261 
262  i = inlen;
263  asn1lenlen = _gss_asn1_get_length_der (in, inlen, &i);
264  if (inlen < i)
265  return -1;
266 
267  inlen -= i;
268  in += i;
269 
270  if (inlen != asn1lenlen)
271  return -1;
272 
273  if (inlen-- == 0)
274  return -1;
275  if (*in++ != '\x06')
276  return -1;
277 
278  i = inlen;
279  asn1lenlen = _gss_asn1_get_length_der (in, inlen, &i);
280  if (inlen < i)
281  return -1;
282 
283  inlen -= i;
284  in += i;
285 
286  if (inlen < asn1lenlen)
287  return -1;
288 
289  *oidlen = asn1lenlen;
290  *oid = (char *) in;
291 
292  inlen -= asn1lenlen;
293  in += asn1lenlen;
294 
295  *outlen = inlen;
296  *out = (char *) in;
297 
298  return 0;
299 }
300 
301 OM_uint32
302 gss_decapsulate_token (const gss_buffer_t input_token,
303  const gss_OID token_oid, gss_buffer_t output_token)
304 {
305  gss_OID_desc tmpoid;
306  char *oid = NULL, *out = NULL;
307  size_t oidlen = 0, outlen = 0;
308 
309  if (!input_token)
310  return GSS_S_CALL_INACCESSIBLE_READ;
311  if (!token_oid)
312  return GSS_S_CALL_INACCESSIBLE_READ;
313  if (!output_token)
314  return GSS_S_CALL_INACCESSIBLE_WRITE;
315 
316  if (_gss_decapsulate_token ((char *) input_token->value,
317  input_token->length,
318  &oid, &oidlen, &out, &outlen) != 0)
319  return GSS_S_DEFECTIVE_TOKEN;
320 
321  tmpoid.length = oidlen;
322  tmpoid.elements = oid;
323 
324  if (!gss_oid_equal (token_oid, &tmpoid))
325  return GSS_S_DEFECTIVE_TOKEN;
326 
327  output_token->length = outlen;
328  output_token->value = malloc (outlen);
329  if (!output_token->value)
330  return GSS_S_FAILURE;
331 
332  memcpy (output_token->value, out, outlen);
333 
334  return GSS_S_COMPLETE;
335 }
336 
337 #endif
#define NULL
Definition: stddef.in.h:72
static int _gss_decapsulate_token(const char *in, size_t inlen, char **oid, size_t *oidlen, char **out, size_t *outlen)
Definition: gss-extra.c:250
OM_uint32 gss_encapsulate_token(const gss_buffer_t input_token, const gss_OID token_oid, gss_buffer_t output_token)
Definition: gss-extra.c:176
OM_uint32 gss_decapsulate_token(const gss_buffer_t input_token, const gss_OID token_oid, gss_buffer_t output_token)
Definition: gss-extra.c:302
static OM_uint32 _gss_encapsulate_token_prefix(const char *prefix, size_t prefixlen, const char *in, size_t inlen, const char *oid, OM_uint32 oidlen, void **out, size_t *outlen)
Definition: gss-extra.c:136
gss_OID GSS_C_NT_HOSTBASED_SERVICE
Definition: gss-extra.c:42
OM_uint32 gss_inquire_mech_for_saslname(OM_uint32 *minor_status, const gss_buffer_t sasl_mech_name, gss_OID *mech_type)
Definition: gss-extra.c:66
static gss_OID_desc tmp
Definition: gss-extra.c:38
int gss_oid_equal(const gss_OID first_oid, const gss_OID second_oid)
Definition: gss-extra.c:49
static size_t _gss_asn1_get_length_der(const char *der, size_t der_len, size_t *len)
Definition: gss-extra.c:206
static void _gss_asn1_length_der(size_t len, unsigned char *ans, size_t *ans_len)
Definition: gss-extra.c:103
int rc
Definition: error.c:42
const char * p
Definition: mbrtowc-impl.h:42