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