2 Unix SMB/CIFS implementation.
4 HTTP library - NTLM authentication mechanism gensec module
6 Copyright (C) 2014 Samuel Cabrero <samuelcabrero@kernevil.me>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "lib/util/tevent_ntstatus.h"
25 #include "auth/auth.h"
26 #include "auth/gensec/gensec.h"
27 #include "auth/gensec/gensec_internal.h"
28 #include "lib/util/base64.h"
30 _PUBLIC_ NTSTATUS
gensec_http_ntlm_init(TALLOC_CTX
*);
32 struct gensec_http_ntlm_state
{
33 struct gensec_security
*sub
;
36 static NTSTATUS
gensec_http_ntlm_client_start(struct gensec_security
*gensec
)
39 struct gensec_http_ntlm_state
*state
;
41 state
= talloc_zero(gensec
, struct gensec_http_ntlm_state
);
43 return NT_STATUS_NO_MEMORY
;
45 gensec
->private_data
= state
;
47 status
= gensec_subcontext_start(state
, gensec
, &state
->sub
);
48 if (!NT_STATUS_IS_OK(status
)) {
52 return gensec_start_mech_by_oid(state
->sub
, GENSEC_OID_NTLMSSP
);
55 struct gensec_http_ntlm_update_state
{
61 static void gensec_http_ntlm_update_done(struct tevent_req
*subreq
);
63 static struct tevent_req
*gensec_http_ntlm_update_send(TALLOC_CTX
*mem_ctx
,
64 struct tevent_context
*ev
,
65 struct gensec_security
*gensec_ctx
,
68 struct gensec_http_ntlm_state
*http_ntlm
=
69 talloc_get_type_abort(gensec_ctx
->private_data
,
70 struct gensec_http_ntlm_state
);
71 struct tevent_req
*req
= NULL
;
72 struct gensec_http_ntlm_update_state
*state
= NULL
;
73 struct tevent_req
*subreq
= NULL
;
75 req
= tevent_req_create(mem_ctx
, &state
,
76 struct gensec_http_ntlm_update_state
);
82 if (strncasecmp((char *)in
.data
, "NTLM ", 5) != 0) {
83 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
84 return tevent_req_post(req
, ev
);
86 state
->ntlm_in
= base64_decode_data_blob_talloc(state
,
90 subreq
= gensec_update_send(state
, ev
,
93 if (tevent_req_nomem(subreq
, req
)) {
94 return tevent_req_post(req
, ev
);
96 tevent_req_set_callback(subreq
, gensec_http_ntlm_update_done
, req
);
101 static void gensec_http_ntlm_update_done(struct tevent_req
*subreq
)
103 struct tevent_req
*req
=
104 tevent_req_callback_data(subreq
,
106 struct gensec_http_ntlm_update_state
*state
=
108 struct gensec_http_ntlm_update_state
);
114 status
= gensec_update_recv(subreq
, state
, &ntlm_out
);
116 state
->status
= status
;
117 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
118 status
= NT_STATUS_OK
;
120 if (tevent_req_nterror(req
, status
)) {
124 b64
= base64_encode_data_blob(state
, ntlm_out
);
125 data_blob_free(&ntlm_out
);
126 if (tevent_req_nomem(b64
, req
)) {
130 str
= talloc_asprintf(state
, "NTLM %s", b64
);
132 if (tevent_req_nomem(str
, req
)) {
136 state
->out
= data_blob_string_const(str
);
137 tevent_req_done(req
);
140 static NTSTATUS
gensec_http_ntlm_update_recv(struct tevent_req
*req
,
141 TALLOC_CTX
*out_mem_ctx
,
144 struct gensec_http_ntlm_update_state
*state
=
146 struct gensec_http_ntlm_update_state
);
149 *out
= data_blob_null
;
151 if (tevent_req_is_nterror(req
, &status
)) {
152 tevent_req_received(req
);
157 talloc_steal(out_mem_ctx
, state
->out
.data
);
158 status
= state
->status
;
159 tevent_req_received(req
);
163 static const struct gensec_security_ops gensec_http_ntlm_security_ops
= {
166 .client_start
= gensec_http_ntlm_client_start
,
167 .update_send
= gensec_http_ntlm_update_send
,
168 .update_recv
= gensec_http_ntlm_update_recv
,
170 .priority
= GENSEC_EXTERNAL
,
173 _PUBLIC_ NTSTATUS
gensec_http_ntlm_init(TALLOC_CTX
*ctx
)
177 status
= gensec_register(ctx
, &gensec_http_ntlm_security_ops
);
178 if (!NT_STATUS_IS_OK(status
)) {
179 DEBUG(0, ("Failed to register '%s' gensec backend!\n",
180 gensec_http_ntlm_security_ops
.name
));