Initial release, version 0.0.0.
[gsasl.git] / lib / ntlm.c
blob6bc91a83b0dced2845c953525f324c7fa9f633fb
1 /* ntlm.c implementation of non-standard SASL mechanism NTLM
2 * Copyright (C) 2002 Simon Josefsson
4 * This file is part of libgsasl.
6 * Libgsasl is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libgsasl 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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with libgsasl; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "internal.h"
24 #ifdef USE_NTLM
26 #include <ntlm.h>
28 struct _Gsasl_ntlm_state {
29 int step;
30 char *username;
32 typedef struct _Gsasl_ntlm_state _Gsasl_ntlm_state;
34 int
35 _gsasl_ntlm_client_init (Gsasl_ctx *ctx)
37 return GSASL_OK;
40 void
41 _gsasl_ntlm_client_done (Gsasl_ctx *ctx)
43 return;
46 int
47 _gsasl_ntlm_client_start (Gsasl_session_ctx *cctx,
48 void **mech_data)
50 _Gsasl_ntlm_state *state;
51 Gsasl_ctx *ctx;
53 ctx = gsasl_client_ctx_get (cctx);
54 if (ctx == NULL)
55 return GSASL_CANNOT_GET_CTX;
57 if (gsasl_client_callback_authorization_id_get (ctx) == NULL)
58 return GSASL_NEED_CLIENT_AUTHORIZATION_ID_CALLBACK;
60 if (gsasl_client_callback_password_get (ctx) == NULL)
61 return GSASL_NEED_CLIENT_PASSWORD_CALLBACK;
63 state = (_Gsasl_ntlm_state*) malloc(sizeof(*state));
64 if (state == NULL)
65 return GSASL_MALLOC_ERROR;
67 state->step = 0;
68 state->username = NULL;
70 *mech_data = state;
72 return GSASL_OK;
75 int
76 _gsasl_ntlm_client_step (Gsasl_session_ctx *cctx,
77 void *mech_data,
78 const char *input,
79 size_t input_len,
80 char *output,
81 size_t *output_len)
83 _Gsasl_ntlm_state *state = mech_data;
84 tSmbNtlmAuthRequest request;
85 tSmbNtlmAuthChallenge challenge;
86 tSmbNtlmAuthResponse response;
87 Gsasl_client_callback_authorization_id cb_authorization_id;
88 Gsasl_client_callback_password cb_password;
89 Gsasl_ctx *ctx;
90 /* XXX create callback for domain? Doesn't seem to be needed by servers */
91 char *domain = NULL;
92 int res;
94 ctx = gsasl_client_ctx_get (cctx);
95 if (ctx == NULL)
96 return GSASL_CANNOT_GET_CTX;
98 cb_authorization_id = gsasl_client_callback_authorization_id_get (ctx);
99 if (cb_authorization_id == NULL)
100 return GSASL_NEED_CLIENT_AUTHORIZATION_ID_CALLBACK;
102 cb_password = gsasl_client_callback_password_get (ctx);
103 if (cb_password == NULL)
104 return GSASL_NEED_CLIENT_PASSWORD_CALLBACK;
106 switch(state->step)
108 case 0:
109 if (input_len == 0)
111 /* Initial client response */
112 *output_len = 0;
113 return GSASL_NEEDS_MORE;
116 if (input_len != 1 && *input != '+')
117 return GSASL_MECHANISM_PARSE_ERROR;
119 res = cb_authorization_id (cctx, output, *output_len);
120 if (res != GSASL_OK)
121 return res;
123 state->username = strdup(output);
125 buildSmbNtlmAuthRequest(&request, state->username, domain);
127 if (*output_len < SmbLength(&request))
128 return GSASL_TOO_SMALL_BUFFER;
130 *output_len = SmbLength(&request);
131 memcpy(output, &request, *output_len);
133 /* dumpSmbNtlmAuthRequest(stdout, &request); */
135 state->step++;
137 res = GSASL_NEEDS_MORE;
138 break;
140 case 1:
141 if (input_len > sizeof(challenge))
142 return GSASL_MECHANISM_PARSE_ERROR;
144 /* Hand crafted challenge for parser testing:
145 TlRMTVNTUAAAAAAAAAAAAAAAAAAAAGFiY2RlZmdoMDEyMzQ1Njc4ODY2NDQwMTIz */
147 memcpy(&challenge, input, input_len);
149 /* XXX? password stored in callee's output buffer */
150 res = cb_password (cctx, output, *output_len);
151 if (res != GSASL_OK)
152 return res;
154 buildSmbNtlmAuthResponse(&challenge, &response, state->username, output);
156 if (*output_len < SmbLength(&response))
157 return GSASL_TOO_SMALL_BUFFER;
159 *output_len = SmbLength(&response);
160 memcpy(output, &response, *output_len);
162 /* dumpSmbNtlmAuthResponse(stdout, &response); */
164 state->step++;
166 res = GSASL_NEEDS_MORE;
167 break;
169 case 2:
170 state->step++;
172 res = GSASL_OK;
173 break;
175 default:
176 res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
177 break;
180 return res;
184 _gsasl_ntlm_client_finish (Gsasl_session_ctx *cctx,
185 void *mech_data)
187 _Gsasl_ntlm_state *state = mech_data;
189 if (state->username)
190 free(state->username);
192 free(state);
194 return GSASL_OK;
197 #endif /* USE_NTLM */