s3-auth split the auth_generic functions into a seperate file
[mat/samba.git] / source3 / auth / auth_generic.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    handle NLTMSSP, server side
5
6    Copyright (C) Andrew Tridgell      2001
7    Copyright (C) Andrew Bartlett 2001-2003,2011
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "auth.h"
25 #include "../auth/ntlmssp/ntlmssp.h"
26 #include "ntlmssp_wrap.h"
27 #include "../librpc/gen_ndr/netlogon.h"
28 #include "../librpc/gen_ndr/dcerpc.h"
29 #include "../lib/tsocket/tsocket.h"
30 #include "auth/gensec/gensec.h"
31 #include "librpc/rpc/dcerpc.h"
32 #include "lib/param/param.h"
33
34 NTSTATUS auth_generic_prepare(const struct tsocket_address *remote_address,
35                               struct auth_generic_state **auth_ntlmssp_state)
36 {
37         struct auth_context *auth_context;
38         struct auth_generic_state *ans;
39         NTSTATUS nt_status;
40
41         ans = talloc_zero(NULL, struct auth_generic_state);
42         if (!ans) {
43                 DEBUG(0,("auth_ntlmssp_start: talloc failed!\n"));
44                 return NT_STATUS_NO_MEMORY;
45         }
46
47         nt_status = make_auth_context_subsystem(talloc_tos(), &auth_context);
48         if (!NT_STATUS_IS_OK(nt_status)) {
49                 TALLOC_FREE(ans);
50                 return nt_status;
51         }
52
53         ans->auth_context = talloc_steal(ans, auth_context);
54
55         if (auth_context->prepare_gensec) {
56                 nt_status = auth_context->prepare_gensec(ans,
57                                                          &ans->gensec_security);
58                 if (!NT_STATUS_IS_OK(nt_status)) {
59                         TALLOC_FREE(ans);
60                         return nt_status;
61                 }
62                 *auth_ntlmssp_state = ans;
63                 return NT_STATUS_OK;
64         } else {
65                 struct gensec_settings *gensec_settings;
66                 struct loadparm_context *lp_ctx;
67
68                 lp_ctx = loadparm_init_s3(ans, loadparm_s3_context());
69                 if (lp_ctx == NULL) {
70                         DEBUG(10, ("loadparm_init_s3 failed\n"));
71                         TALLOC_FREE(ans);
72                         return NT_STATUS_INVALID_SERVER_STATE;
73                 }
74
75                 gensec_settings = lpcfg_gensec_settings(ans, lp_ctx);
76                 if (lp_ctx == NULL) {
77                         DEBUG(10, ("lpcfg_gensec_settings failed\n"));
78                         TALLOC_FREE(ans);
79                         return NT_STATUS_NO_MEMORY;
80                 }
81
82                 nt_status = gensec_server_start(ans, gensec_settings,
83                                                 NULL, &ans->gensec_security);
84
85                 if (!NT_STATUS_IS_OK(nt_status)) {
86                         TALLOC_FREE(ans);
87                         return nt_status;
88                 }
89                 talloc_unlink(ans, lp_ctx);
90                 talloc_unlink(ans, gensec_settings);
91         }
92
93         nt_status = gensec_set_remote_address(ans->gensec_security,
94                                               remote_address);
95         if (!NT_STATUS_IS_OK(nt_status)) {
96                 TALLOC_FREE(ans);
97                 return nt_status;
98         }
99
100         *auth_ntlmssp_state = ans;
101         return NT_STATUS_OK;
102 }
103
104 NTSTATUS auth_generic_start(struct auth_generic_state *auth_ntlmssp_state, const char *oid)
105 {
106         struct gensec_ntlmssp_context *gensec_ntlmssp;
107         NTSTATUS status;
108
109         if (auth_ntlmssp_state->auth_context->gensec_start_mech_by_oid) {
110                 return auth_ntlmssp_state->auth_context->gensec_start_mech_by_oid(
111                                 auth_ntlmssp_state->gensec_security, oid);
112         }
113
114         if (strcmp(oid, GENSEC_OID_NTLMSSP) != 0) {
115                 return NT_STATUS_NOT_IMPLEMENTED;
116         }
117
118         status = gensec_start_mech_by_ops(auth_ntlmssp_state->gensec_security,
119                                           &gensec_ntlmssp3_server_ops);
120         if (!NT_STATUS_IS_OK(status)) {
121                 return status;
122         }
123
124         gensec_ntlmssp =
125                 talloc_get_type_abort(auth_ntlmssp_state->gensec_security->private_data,
126                                       struct gensec_ntlmssp_context);
127
128         gensec_ntlmssp->auth_context = talloc_move(gensec_ntlmssp, &auth_ntlmssp_state->auth_context);
129
130         return NT_STATUS_OK;
131 }
132
133 NTSTATUS auth_generic_authtype_start(struct auth_generic_state *auth_ntlmssp_state,
134                                      uint8_t auth_type, uint8_t auth_level)
135 {
136         struct gensec_ntlmssp_context *gensec_ntlmssp;
137         NTSTATUS status;
138
139         if (auth_ntlmssp_state->auth_context->gensec_start_mech_by_authtype) {
140                 return auth_ntlmssp_state->auth_context->gensec_start_mech_by_authtype(
141                                 auth_ntlmssp_state->gensec_security,
142                                 auth_type, auth_level);
143         }
144
145         if (auth_type != DCERPC_AUTH_TYPE_NTLMSSP) {
146                 /* The caller will then free the auth_ntlmssp_state,
147                  * undoing what was done in auth_generic_prepare().
148                  *
149                  * We can't do that logic here, as
150                  * auth_ntlmssp_want_feature() may have been called in
151                  * between.
152                  */
153                 return NT_STATUS_NOT_IMPLEMENTED;
154         }
155
156         gensec_want_feature(auth_ntlmssp_state->gensec_security,
157                             GENSEC_FEATURE_DCE_STYLE);
158         gensec_want_feature(auth_ntlmssp_state->gensec_security,
159                             GENSEC_FEATURE_ASYNC_REPLIES);
160         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
161                 gensec_want_feature(auth_ntlmssp_state->gensec_security,
162                                     GENSEC_FEATURE_SIGN);
163         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
164                 gensec_want_feature(auth_ntlmssp_state->gensec_security,
165                                     GENSEC_FEATURE_SIGN);
166                 gensec_want_feature(auth_ntlmssp_state->gensec_security,
167                                     GENSEC_FEATURE_SEAL);
168         } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
169                 /* Default features */
170         } else {
171                 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
172                          auth_level));
173                 return NT_STATUS_INVALID_PARAMETER;
174         }
175
176         status = gensec_start_mech_by_ops(auth_ntlmssp_state->gensec_security,
177                                           &gensec_ntlmssp3_server_ops);
178         if (!NT_STATUS_IS_OK(status)) {
179                 return status;
180         }
181
182         gensec_ntlmssp =
183                 talloc_get_type_abort(auth_ntlmssp_state->gensec_security->private_data,
184                                       struct gensec_ntlmssp_context);
185
186         gensec_ntlmssp->auth_context = talloc_move(gensec_ntlmssp, &auth_ntlmssp_state->auth_context);
187
188         return NT_STATUS_OK;
189 }