Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : HTTP library - Basic authentication mechanism gensec module
5 :
6 : Copyright (C) 2014 Samuel Cabrero <samuelcabrero@kernevil.me>
7 :
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.
12 :
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.
17 :
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/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include <tevent.h>
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 "auth/credentials/credentials.h"
29 : #include "lib/util/base64.h"
30 :
31 : _PUBLIC_ NTSTATUS gensec_http_basic_init(TALLOC_CTX *);
32 :
33 : struct gensec_http_basic_state {
34 : enum {
35 : GENSEC_HTTP_BASIC_START,
36 : GENSEC_HTTP_BASIC_DONE,
37 : GENSEC_HTTP_BASIC_ERROR,
38 : } step;
39 : };
40 :
41 14 : static NTSTATUS gensec_http_basic_client_start(struct gensec_security *gensec)
42 : {
43 0 : struct gensec_http_basic_state *state;
44 :
45 14 : state = talloc_zero(gensec, struct gensec_http_basic_state);
46 14 : if (state == NULL) {
47 0 : return NT_STATUS_NO_MEMORY;
48 : }
49 14 : gensec->private_data = state;
50 :
51 14 : state->step = GENSEC_HTTP_BASIC_START;
52 :
53 14 : return NT_STATUS_OK;
54 : }
55 :
56 : struct gensec_http_basic_update_state {
57 : NTSTATUS status;
58 : DATA_BLOB out;
59 : };
60 :
61 : static NTSTATUS gensec_http_basic_update_internal(struct gensec_security *gensec_ctx,
62 : TALLOC_CTX *mem_ctx,
63 : const DATA_BLOB in,
64 : DATA_BLOB *out);
65 :
66 14 : static struct tevent_req *gensec_http_basic_update_send(TALLOC_CTX *mem_ctx,
67 : struct tevent_context *ev,
68 : struct gensec_security *gensec_security,
69 : const DATA_BLOB in)
70 : {
71 14 : struct tevent_req *req = NULL;
72 14 : struct gensec_http_basic_update_state *state = NULL;
73 0 : NTSTATUS status;
74 :
75 14 : req = tevent_req_create(mem_ctx, &state,
76 : struct gensec_http_basic_update_state);
77 14 : if (req == NULL) {
78 0 : return NULL;
79 : }
80 :
81 14 : status = gensec_http_basic_update_internal(gensec_security,
82 : state, in,
83 14 : &state->out);
84 14 : state->status = status;
85 14 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
86 0 : tevent_req_done(req);
87 0 : return tevent_req_post(req, ev);
88 : }
89 14 : if (tevent_req_nterror(req, status)) {
90 0 : return tevent_req_post(req, ev);
91 : }
92 :
93 14 : tevent_req_done(req);
94 14 : return tevent_req_post(req, ev);
95 : }
96 :
97 14 : static NTSTATUS gensec_http_basic_update_internal(struct gensec_security *gensec_ctx,
98 : TALLOC_CTX *mem_ctx,
99 : const DATA_BLOB in,
100 : DATA_BLOB *out)
101 : {
102 0 : struct gensec_http_basic_state *state;
103 0 : struct cli_credentials *creds;
104 0 : char *tmp, *b64;
105 :
106 14 : state = talloc_get_type_abort(gensec_ctx->private_data,
107 : struct gensec_http_basic_state);
108 14 : creds = gensec_get_credentials(gensec_ctx);
109 :
110 14 : switch (gensec_ctx->gensec_role) {
111 14 : case GENSEC_CLIENT:
112 14 : switch (state->step) {
113 14 : case GENSEC_HTTP_BASIC_START:
114 14 : tmp = talloc_asprintf(mem_ctx, "%s\\%s:%s",
115 : cli_credentials_get_domain(creds),
116 : cli_credentials_get_username(creds),
117 : cli_credentials_get_password(creds));
118 14 : if (tmp == NULL) {
119 0 : state->step = GENSEC_HTTP_BASIC_ERROR;
120 0 : return NT_STATUS_NO_MEMORY;
121 : }
122 14 : *out = data_blob_string_const(tmp);
123 :
124 14 : b64 = base64_encode_data_blob(mem_ctx, *out);
125 14 : if (b64 == NULL) {
126 0 : state->step = GENSEC_HTTP_BASIC_ERROR;
127 0 : return NT_STATUS_NO_MEMORY;
128 : }
129 14 : TALLOC_FREE(tmp);
130 :
131 14 : tmp = talloc_asprintf(mem_ctx, "Basic %s", b64);
132 14 : if (tmp == NULL) {
133 0 : state->step = GENSEC_HTTP_BASIC_ERROR;
134 0 : return NT_STATUS_NO_MEMORY;
135 : }
136 14 : TALLOC_FREE(b64);
137 :
138 14 : *out = data_blob_string_const(tmp);
139 14 : state->step = GENSEC_HTTP_BASIC_DONE;
140 14 : return NT_STATUS_OK;
141 :
142 0 : case GENSEC_HTTP_BASIC_DONE:
143 : case GENSEC_HTTP_BASIC_ERROR:
144 : default:
145 0 : break;
146 : }
147 0 : state->step = GENSEC_HTTP_BASIC_ERROR;
148 0 : return NT_STATUS_INTERNAL_ERROR;
149 :
150 0 : case GENSEC_SERVER:
151 0 : state->step = GENSEC_HTTP_BASIC_ERROR;
152 0 : return NT_STATUS_NOT_IMPLEMENTED;
153 : }
154 :
155 0 : state->step = GENSEC_HTTP_BASIC_ERROR;
156 0 : return NT_STATUS_INTERNAL_ERROR;
157 : }
158 :
159 14 : static NTSTATUS gensec_http_basic_update_recv(struct tevent_req *req,
160 : TALLOC_CTX *out_mem_ctx,
161 : DATA_BLOB *out)
162 : {
163 0 : struct gensec_http_basic_update_state *state =
164 14 : tevent_req_data(req,
165 : struct gensec_http_basic_update_state);
166 0 : NTSTATUS status;
167 :
168 14 : *out = data_blob_null;
169 :
170 14 : if (tevent_req_is_nterror(req, &status)) {
171 0 : tevent_req_received(req);
172 0 : return status;
173 : }
174 :
175 14 : *out = state->out;
176 14 : talloc_steal(out_mem_ctx, state->out.data);
177 14 : status = state->status;
178 14 : tevent_req_received(req);
179 14 : return status;
180 : }
181 :
182 : static const struct gensec_security_ops gensec_http_basic_security_ops = {
183 : .name = "http_basic",
184 : .auth_type = 0,
185 : .client_start = gensec_http_basic_client_start,
186 : .update_send = gensec_http_basic_update_send,
187 : .update_recv = gensec_http_basic_update_recv,
188 : .enabled = true,
189 : .priority = GENSEC_EXTERNAL,
190 : };
191 :
192 52291 : _PUBLIC_ NTSTATUS gensec_http_basic_init(TALLOC_CTX *ctx)
193 : {
194 1208 : NTSTATUS status;
195 :
196 52291 : status = gensec_register(ctx, &gensec_http_basic_security_ops);
197 52291 : if (!NT_STATUS_IS_OK(status)) {
198 0 : DEBUG(0, ("Failed to register '%s' gensec backend!\n",
199 : gensec_http_basic_security_ops.name));
200 0 : return status;
201 : }
202 :
203 52291 : return status;
204 : }
|