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
28 struct _Gsasl_ntlm_state
{
32 typedef struct _Gsasl_ntlm_state _Gsasl_ntlm_state
;
35 _gsasl_ntlm_client_init (Gsasl_ctx
*ctx
)
41 _gsasl_ntlm_client_done (Gsasl_ctx
*ctx
)
47 _gsasl_ntlm_client_start (Gsasl_session_ctx
*cctx
,
50 _Gsasl_ntlm_state
*state
;
53 ctx
= gsasl_client_ctx_get (cctx
);
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
));
65 return GSASL_MALLOC_ERROR
;
68 state
->username
= NULL
;
76 _gsasl_ntlm_client_step (Gsasl_session_ctx
*cctx
,
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
;
90 /* XXX create callback for domain? Doesn't seem to be needed by servers */
94 ctx
= gsasl_client_ctx_get (cctx
);
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
;
111 /* Initial client response */
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
);
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); */
137 res
= GSASL_NEEDS_MORE
;
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
);
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); */
166 res
= GSASL_NEEDS_MORE
;
176 res
= GSASL_MECHANISM_CALLED_TOO_MANY_TIMES
;
184 _gsasl_ntlm_client_finish (Gsasl_session_ctx
*cctx
,
187 _Gsasl_ntlm_state
*state
= mech_data
;
190 free(state
->username
);
197 #endif /* USE_NTLM */