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)  

server.c
Go to the documentation of this file.
1 /* server.c --- SASL mechanism GSSAPI as defined in RFC 4752, server side.
2  * Copyright (C) 2002-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 malloc, free. */
28 #include <stdlib.h>
29 
30 /* Get memcpy, strlen. */
31 #include <string.h>
32 
33 /* Get specification. */
34 #include "x-gssapi.h"
35 
36 #ifdef HAVE_LIBGSS
37 #include <gss.h>
38 #elif HAVE_GSSAPI_H
39 #include <gssapi.h>
40 #elif HAVE_GSSAPI_GSSAPI_H
41 #include <gssapi/gssapi.h>
42 #endif
43 
44 #include "gss-extra.h"
45 
47 {
48  int step;
49  gss_name_t client;
50  gss_cred_id_t cred;
51  gss_ctx_id_t context;
52 };
54 
55 int
56 _gsasl_gssapi_server_start (Gsasl_session * sctx, void **mech_data)
57 {
59 
60  state = (_Gsasl_gssapi_server_state *) malloc (sizeof (*state));
61  if (state == NULL)
62  return GSASL_MALLOC_ERROR;
63 
64  state->step = 0;
65  state->cred = GSS_C_NO_CREDENTIAL;
66  state->context = GSS_C_NO_CONTEXT;
67  state->client = NULL;
68  *mech_data = state;
69 
70  return GSASL_OK;
71 }
72 
73 int
75  void *mech_data,
76  const char *input, size_t input_len,
77  char **output, size_t *output_len)
78 {
79  _Gsasl_gssapi_server_state *state = mech_data;
80  gss_buffer_desc bufdesc1, bufdesc2;
81  OM_uint32 maj_stat, min_stat;
82  gss_buffer_desc client_name;
83  gss_OID mech_type;
84  char tmp[4];
85  int res;
86 
87  *output = NULL;
88  *output_len = 0;
89 
90  switch (state->step)
91  {
92  case 0:
93  {
94  gss_name_t server;
95  const char *service;
96  const char *hostname;
97 
98  if (input_len == 0)
99  {
101  break;
102  }
103 
104  service = gsasl_property_get (sctx, GSASL_SERVICE);
105  if (!service)
106  return GSASL_NO_SERVICE;
107 
108  hostname = gsasl_property_get (sctx, GSASL_HOSTNAME);
109  if (!hostname)
110  return GSASL_NO_HOSTNAME;
111 
112  /* FIXME: Use asprintf. */
113 
114  bufdesc1.length = strlen (service) + strlen ("@")
115  + strlen (hostname) + 1;
116  bufdesc1.value = malloc (bufdesc1.length);
117  if (bufdesc1.value == NULL)
118  return GSASL_MALLOC_ERROR;
119 
120  sprintf (bufdesc1.value, "%s@%s", service, hostname);
121 
122  maj_stat = gss_import_name (&min_stat, &bufdesc1,
123  GSS_C_NT_HOSTBASED_SERVICE, &server);
124  free (bufdesc1.value);
125  if (GSS_ERROR (maj_stat))
127 
128  maj_stat = gss_acquire_cred (&min_stat, server, 0,
129  GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
130  &state->cred, NULL, NULL);
131  gss_release_name (&min_stat, &server);
132  if (GSS_ERROR (maj_stat))
134  }
135  state->step++;
136  /* fall through */
137 
138  case 1:
139  bufdesc1.value = (void *) input;
140  bufdesc1.length = input_len;
141  if (state->client)
142  {
143  gss_release_name (&min_stat, &state->client);
144  state->client = GSS_C_NO_NAME;
145  }
146 
147  maj_stat = gss_accept_sec_context (&min_stat,
148  &state->context,
149  state->cred,
150  &bufdesc1,
151  GSS_C_NO_CHANNEL_BINDINGS,
152  &state->client,
153  &mech_type,
154  &bufdesc2, NULL, NULL, NULL);
155  if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
157 
158  if (maj_stat == GSS_S_COMPLETE)
159  state->step++;
160 
161  if (maj_stat == GSS_S_CONTINUE_NEEDED || bufdesc2.length > 0)
162  {
163  *output = malloc (bufdesc2.length);
164  if (!*output)
165  return GSASL_MALLOC_ERROR;
166  memcpy (*output, bufdesc2.value, bufdesc2.length);
167  *output_len = bufdesc2.length;
168  }
169 
170  maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
171  if (GSS_ERROR (maj_stat))
173 
174  if (maj_stat == GSS_S_CONTINUE_NEEDED || *output_len > 0)
175  {
177  break;
178  }
179  /* fall through */
180 
181  case 2:
182  memset (tmp, 0xFF, 4);
183  tmp[0] = GSASL_QOP_AUTH;
184  bufdesc1.length = 4;
185  bufdesc1.value = tmp;
186  maj_stat = gss_wrap (&min_stat, state->context, 0, GSS_C_QOP_DEFAULT,
187  &bufdesc1, NULL, &bufdesc2);
188  if (GSS_ERROR (maj_stat))
190 
191  *output = malloc (bufdesc2.length);
192  if (!*output)
193  return GSASL_MALLOC_ERROR;
194  memcpy (*output, bufdesc2.value, bufdesc2.length);
195  *output_len = bufdesc2.length;
196 
197  maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
198  if (GSS_ERROR (maj_stat))
200 
201  state->step++;
203  break;
204 
205  case 3:
206  bufdesc1.value = (void *) input;
207  bufdesc1.length = input_len;
208  maj_stat = gss_unwrap (&min_stat, state->context, &bufdesc1,
209  &bufdesc2, NULL, NULL);
210  if (GSS_ERROR (maj_stat))
212 
213  /* [RFC 2222 section 7.2.1]:
214  The client passes this token to GSS_Unwrap and interprets the
215  first octet of resulting cleartext as a bit-mask specifying
216  the security layers supported by the server and the second
217  through fourth octets as the maximum size output_message to
218  send to the server. The client then constructs data, with
219  the first octet containing the bit-mask specifying the
220  selected security layer, the second through fourth octets
221  containing in network byte order the maximum size
222  output_message the client is able to receive, and the
223  remaining octets containing the authorization identity. The
224  client passes the data to GSS_Wrap with conf_flag set to
225  FALSE, and responds with the generated output_message. The
226  client can then consider the server authenticated. */
227 
228  if ((((char *) bufdesc2.value)[0] & GSASL_QOP_AUTH) == 0)
229  {
230  /* Integrity or privacy unsupported */
231  maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
233  }
234 
236  (char *) bufdesc2.value + 4,
237  bufdesc2.length - 4);
238 
239  maj_stat = gss_display_name (&min_stat, state->client,
240  &client_name, &mech_type);
241  if (GSS_ERROR (maj_stat))
243 
245  client_name.value, client_name.length);
246 
247  maj_stat = gss_release_buffer (&min_stat, &client_name);
248  if (GSS_ERROR (maj_stat))
250 
251  maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
252  if (GSS_ERROR (maj_stat))
254 
256 
257  state->step++;
258  break;
259 
260  default:
262  break;
263  }
264 
265  return res;
266 }
267 
268 void
270 {
271  _Gsasl_gssapi_server_state *state = mech_data;
272  OM_uint32 min_stat;
273 
274  if (!state)
275  return;
276 
277  if (state->context != GSS_C_NO_CONTEXT)
278  gss_delete_sec_context (&min_stat, &state->context, GSS_C_NO_BUFFER);
279 
280  if (state->cred != GSS_C_NO_CREDENTIAL)
281  gss_release_cred (&min_stat, &state->cred);
282 
283  if (state->client != GSS_C_NO_NAME)
284  gss_release_name (&min_stat, &state->client);
285 
286  free (state);
287 }
int gsasl_callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop)
Definition: callback.c:75
#define NULL
Definition: stddef.in.h:72
const char * gsasl_property_get(Gsasl_session *sctx, Gsasl_property prop)
Definition: property.c:263
@ GSASL_QOP_AUTH
Definition: gsasl.h:235
@ GSASL_GSSAPI_UNWRAP_ERROR
Definition: gsasl.h:202
@ GSASL_GSSAPI_IMPORT_NAME_ERROR
Definition: gsasl.h:199
@ GSASL_OK
Definition: gsasl.h:171
@ GSASL_GSSAPI_RELEASE_BUFFER_ERROR
Definition: gsasl.h:198
@ GSASL_GSSAPI_ACCEPT_SEC_CONTEXT_ERROR
Definition: gsasl.h:201
@ GSASL_NEEDS_MORE
Definition: gsasl.h:172
@ GSASL_MALLOC_ERROR
Definition: gsasl.h:175
@ GSASL_GSSAPI_DISPLAY_NAME_ERROR
Definition: gsasl.h:205
@ GSASL_NO_SERVICE
Definition: gsasl.h:191
@ GSASL_GSSAPI_ACQUIRE_CRED_ERROR
Definition: gsasl.h:204
@ GSASL_MECHANISM_CALLED_TOO_MANY_TIMES
Definition: gsasl.h:174
@ GSASL_NO_HOSTNAME
Definition: gsasl.h:192
@ GSASL_GSSAPI_WRAP_ERROR
Definition: gsasl.h:203
@ GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR
Definition: gsasl.h:206
void gsasl_property_set_raw(Gsasl_session *sctx, Gsasl_property prop, const char *data, size_t len)
Definition: property.c:184
@ GSASL_HOSTNAME
Definition: gsasl.h:340
@ GSASL_AUTHZID
Definition: gsasl.h:336
@ GSASL_VALIDATE_GSSAPI
Definition: gsasl.h:366
@ GSASL_SERVICE
Definition: gsasl.h:339
@ GSASL_GSSAPI_DISPLAY_NAME
Definition: gsasl.h:341
gss_OID GSS_C_NT_HOSTBASED_SERVICE
Definition: gss-extra.c:42
static gss_OID_desc tmp
Definition: gss-extra.c:38
void _gsasl_gssapi_server_finish(Gsasl_session *sctx, void *mech_data)
Definition: server.c:269
int _gsasl_gssapi_server_start(Gsasl_session *sctx, void **mech_data)
Definition: server.c:56
int _gsasl_gssapi_server_step(Gsasl_session *sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t *output_len)
Definition: server.c:74
int res
Definition: mbrtowc-impl.h:45
gss_ctx_id_t context
Definition: server.c:51
gss_cred_id_t cred
Definition: server.c:50