4a488a34bfa4aeac79fe1338a3b66e226bf3dc63
[samba.git] / source4 / lib / http / gensec / basic.c
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 "auth/auth.h"
24 #include "auth/gensec/gensec.h"
25 #include "auth/gensec/gensec_internal.h"
26 #include "auth/credentials/credentials.h"
27 #include "lib/util/base64.h"
28
29 _PUBLIC_ NTSTATUS gensec_http_basic_init(void);
30
31 struct gensec_http_basic_state {
32         enum {
33                 GENSEC_HTTP_BASIC_START,
34                 GENSEC_HTTP_BASIC_DONE,
35                 GENSEC_HTTP_BASIC_ERROR,
36         } step;
37 };
38
39 static NTSTATUS gensec_http_basic_client_start(struct gensec_security *gensec)
40 {
41         struct gensec_http_basic_state *state;
42
43         state = talloc_zero(gensec, struct gensec_http_basic_state);
44         if (state == NULL) {
45                 return NT_STATUS_NO_MEMORY;
46         }
47         gensec->private_data = state;
48
49         state->step = GENSEC_HTTP_BASIC_START;
50
51         return NT_STATUS_OK;
52 }
53
54 static NTSTATUS gensec_http_basic_update(struct gensec_security *gensec_ctx,
55                                          TALLOC_CTX *mem_ctx,
56                                          struct tevent_context *ev,
57                                          const DATA_BLOB in,
58                                          DATA_BLOB *out)
59 {
60         struct gensec_http_basic_state *state;
61         struct cli_credentials *creds;
62         char *tmp, *b64;
63
64         state = talloc_get_type_abort(gensec_ctx->private_data,
65                                       struct gensec_http_basic_state);
66         creds = gensec_get_credentials(gensec_ctx);
67
68         switch (gensec_ctx->gensec_role) {
69         case GENSEC_CLIENT:
70                 switch (state->step) {
71                 case GENSEC_HTTP_BASIC_START:
72                         tmp = talloc_asprintf(mem_ctx, "%s\\%s:%s",
73                                         cli_credentials_get_domain(creds),
74                                         cli_credentials_get_username(creds),
75                                         cli_credentials_get_password(creds));
76                         if (tmp == NULL) {
77                                 state->step = GENSEC_HTTP_BASIC_ERROR;
78                                 return NT_STATUS_NO_MEMORY;
79                         }
80                         *out = data_blob_string_const(tmp);
81
82                         b64 = base64_encode_data_blob(mem_ctx, *out);
83                         if (b64 == NULL) {
84                                 state->step = GENSEC_HTTP_BASIC_ERROR;
85                                 return NT_STATUS_NO_MEMORY;
86                         }
87                         TALLOC_FREE(tmp);
88
89                         tmp = talloc_asprintf(mem_ctx, "Basic %s", b64);
90                         if (tmp == NULL) {
91                                 state->step = GENSEC_HTTP_BASIC_ERROR;
92                                 return NT_STATUS_NO_MEMORY;
93                         }
94                         TALLOC_FREE(b64);
95
96                         *out = data_blob_string_const(tmp);
97                         state->step = GENSEC_HTTP_BASIC_DONE;
98                         return NT_STATUS_OK;
99
100                 case GENSEC_HTTP_BASIC_DONE:
101                 case GENSEC_HTTP_BASIC_ERROR:
102                 default:
103                         break;
104                 }
105                 state->step = GENSEC_HTTP_BASIC_ERROR;
106                 return NT_STATUS_INTERNAL_ERROR;
107
108         case GENSEC_SERVER:
109                 state->step = GENSEC_HTTP_BASIC_ERROR;
110                 return NT_STATUS_NOT_IMPLEMENTED;
111         }
112
113         state->step = GENSEC_HTTP_BASIC_ERROR;
114         return NT_STATUS_INTERNAL_ERROR;
115 }
116
117 static const struct gensec_security_ops gensec_http_basic_security_ops = {
118         .name           = "http_basic",
119         .auth_type      = 0,
120         .client_start   = gensec_http_basic_client_start,
121         .update         = gensec_http_basic_update,
122         .enabled        = true,
123         .priority       = GENSEC_EXTERNAL,
124 };
125
126 _PUBLIC_ NTSTATUS gensec_http_basic_init(void)
127 {
128         NTSTATUS status;
129
130         status = gensec_register(&gensec_http_basic_security_ops);
131         if (!NT_STATUS_IS_OK(status)) {
132                 DEBUG(0, ("Failed to register '%s' gensec backend!\n",
133                                 gensec_http_basic_security_ops.name));
134                 return status;
135         }
136
137         return status;
138 }