1 /*
2    Unix SMB/CIFS implementation.
3 
4    Generic Authentication Interface
5 
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2006
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/gensec/gensec.h"
25 #include "auth/gensec/gensec_internal.h"
26 #include "auth/common_auth.h"
27 #include "../lib/util/asn1.h"
28 
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_AUTH
31 
gensec_generate_session_info_pac(TALLOC_CTX * mem_ctx,struct gensec_security * gensec_security,struct smb_krb5_context * smb_krb5_context,DATA_BLOB * pac_blob,const char * principal_string,const struct tsocket_address * remote_address,struct auth_session_info ** session_info)32 NTSTATUS gensec_generate_session_info_pac(TALLOC_CTX *mem_ctx,
33 					  struct gensec_security *gensec_security,
34 					  struct smb_krb5_context *smb_krb5_context,
35 					  DATA_BLOB *pac_blob,
36 					  const char *principal_string,
37 					  const struct tsocket_address *remote_address,
38 					  struct auth_session_info **session_info)
39 {
40 	uint32_t session_info_flags = 0;
41 
42 	if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
43 		session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
44 	}
45 
46 	session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
47 
48 	if (!pac_blob) {
49 		if (gensec_setting_bool(gensec_security->settings, "gensec", "require_pac", false)) {
50 			DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access\n",
51 				  principal_string));
52 			return NT_STATUS_ACCESS_DENIED;
53 		}
54 		DBG_NOTICE("Unable to find PAC for %s, resorting to local "
55 			   "user lookup\n", principal_string);
56 	}
57 
58 	if (gensec_security->auth_context && gensec_security->auth_context->generate_session_info_pac) {
59 		return gensec_security->auth_context->generate_session_info_pac(gensec_security->auth_context,
60 										mem_ctx,
61 										smb_krb5_context,
62 										pac_blob,
63 										principal_string,
64 										remote_address,
65 										session_info_flags,
66 										session_info);
67 	} else {
68 		DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
69 		return NT_STATUS_INTERNAL_ERROR;
70 	}
71 }
72 
73 /*
74   magic check a GSS-API wrapper packet for an Kerberos OID
75 */
gensec_gssapi_check_oid(const DATA_BLOB * blob,const char * oid)76 static bool gensec_gssapi_check_oid(const DATA_BLOB *blob, const char *oid)
77 {
78 	bool ret = false;
79 	struct asn1_data *data = asn1_init(NULL, ASN1_MAX_TREE_DEPTH);
80 
81 	if (!data) return false;
82 
83 	if (!asn1_load(data, *blob)) goto err;
84 	if (!asn1_start_tag(data, ASN1_APPLICATION(0))) goto err;
85 	if (!asn1_check_OID(data, oid)) goto err;
86 
87 	ret = !asn1_has_error(data);
88 
89   err:
90 
91 	asn1_free(data);
92 	return ret;
93 }
94 
95 /**
96  * Check if the packet is one for the KRB5 mechansim
97  *
98  * NOTE: This is a helper that can be employed by multiple mechanisms, do
99  * not make assumptions about the private_data
100  *
101  * @param gensec_security GENSEC state, unused
102  * @param in The request, as a DATA_BLOB
103  * @return Error, INVALID_PARAMETER if it's not a packet for us
104  *                or NT_STATUS_OK if the packet is ok.
105  */
106 
gensec_magic_check_krb5_oid(struct gensec_security * unused,const DATA_BLOB * blob)107 NTSTATUS gensec_magic_check_krb5_oid(struct gensec_security *unused,
108 					const DATA_BLOB *blob)
109 {
110 	if (gensec_gssapi_check_oid(blob, GENSEC_OID_KERBEROS5)) {
111 		return NT_STATUS_OK;
112 	} else {
113 		return NT_STATUS_INVALID_PARAMETER;
114 	}
115 }
116 
gensec_child_want_feature(struct gensec_security * gensec_security,uint32_t feature)117 void gensec_child_want_feature(struct gensec_security *gensec_security,
118 			       uint32_t feature)
119 {
120 	struct gensec_security *child_security = gensec_security->child_security;
121 
122 	gensec_security->want_features |= feature;
123 	if (child_security == NULL) {
124 		return;
125 	}
126 	gensec_want_feature(child_security, feature);
127 }
128 
gensec_child_have_feature(struct gensec_security * gensec_security,uint32_t feature)129 bool gensec_child_have_feature(struct gensec_security *gensec_security,
130 			       uint32_t feature)
131 {
132 	struct gensec_security *child_security = gensec_security->child_security;
133 
134 	if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
135 		/*
136 		 * All mechs with sub (child) mechs need to provide DCERPC
137 		 * header signing! This is required because the negotiation
138 		 * of header signing is done before the authentication
139 		 * is completed.
140 		 */
141 		return true;
142 	}
143 
144 	if (child_security == NULL) {
145 		return false;
146 	}
147 
148 	return gensec_have_feature(child_security, feature);
149 }
150 
gensec_child_unseal_packet(struct gensec_security * gensec_security,uint8_t * data,size_t length,const uint8_t * whole_pdu,size_t pdu_length,const DATA_BLOB * sig)151 NTSTATUS gensec_child_unseal_packet(struct gensec_security *gensec_security,
152 				    uint8_t *data, size_t length,
153 				    const uint8_t *whole_pdu, size_t pdu_length,
154 				    const DATA_BLOB *sig)
155 {
156 	if (gensec_security->child_security == NULL) {
157 		return NT_STATUS_INVALID_PARAMETER;
158 	}
159 
160 	return gensec_unseal_packet(gensec_security->child_security,
161 				    data, length,
162 				    whole_pdu, pdu_length,
163 				    sig);
164 }
165 
gensec_child_check_packet(struct gensec_security * gensec_security,const uint8_t * data,size_t length,const uint8_t * whole_pdu,size_t pdu_length,const DATA_BLOB * sig)166 NTSTATUS gensec_child_check_packet(struct gensec_security *gensec_security,
167 				   const uint8_t *data, size_t length,
168 				   const uint8_t *whole_pdu, size_t pdu_length,
169 				   const DATA_BLOB *sig)
170 {
171 	if (gensec_security->child_security == NULL) {
172 		return NT_STATUS_INVALID_PARAMETER;
173 	}
174 
175 	return gensec_check_packet(gensec_security->child_security,
176 				   data, length,
177 				   whole_pdu, pdu_length,
178 				   sig);
179 }
180 
gensec_child_seal_packet(struct gensec_security * gensec_security,TALLOC_CTX * mem_ctx,uint8_t * data,size_t length,const uint8_t * whole_pdu,size_t pdu_length,DATA_BLOB * sig)181 NTSTATUS gensec_child_seal_packet(struct gensec_security *gensec_security,
182 				  TALLOC_CTX *mem_ctx,
183 				  uint8_t *data, size_t length,
184 				  const uint8_t *whole_pdu, size_t pdu_length,
185 				  DATA_BLOB *sig)
186 {
187 	if (gensec_security->child_security == NULL) {
188 		return NT_STATUS_INVALID_PARAMETER;
189 	}
190 
191 	return gensec_seal_packet(gensec_security->child_security,
192 				  mem_ctx,
193 				  data, length,
194 				  whole_pdu, pdu_length,
195 				  sig);
196 }
197 
gensec_child_sign_packet(struct gensec_security * gensec_security,TALLOC_CTX * mem_ctx,const uint8_t * data,size_t length,const uint8_t * whole_pdu,size_t pdu_length,DATA_BLOB * sig)198 NTSTATUS gensec_child_sign_packet(struct gensec_security *gensec_security,
199 				  TALLOC_CTX *mem_ctx,
200 				  const uint8_t *data, size_t length,
201 				  const uint8_t *whole_pdu, size_t pdu_length,
202 				  DATA_BLOB *sig)
203 {
204 	if (gensec_security->child_security == NULL) {
205 		return NT_STATUS_INVALID_PARAMETER;
206 	}
207 
208 	return gensec_sign_packet(gensec_security->child_security,
209 				  mem_ctx,
210 				  data, length,
211 				  whole_pdu, pdu_length,
212 				  sig);
213 }
214 
gensec_child_wrap(struct gensec_security * gensec_security,TALLOC_CTX * mem_ctx,const DATA_BLOB * in,DATA_BLOB * out)215 NTSTATUS gensec_child_wrap(struct gensec_security *gensec_security,
216 			   TALLOC_CTX *mem_ctx,
217 			   const DATA_BLOB *in,
218 			   DATA_BLOB *out)
219 {
220 	if (gensec_security->child_security == NULL) {
221 		return NT_STATUS_INVALID_PARAMETER;
222 	}
223 
224 	return gensec_wrap(gensec_security->child_security,
225 			   mem_ctx, in, out);
226 }
227 
gensec_child_unwrap(struct gensec_security * gensec_security,TALLOC_CTX * mem_ctx,const DATA_BLOB * in,DATA_BLOB * out)228 NTSTATUS gensec_child_unwrap(struct gensec_security *gensec_security,
229 			     TALLOC_CTX *mem_ctx,
230 			     const DATA_BLOB *in,
231 			     DATA_BLOB *out)
232 {
233 	if (gensec_security->child_security == NULL) {
234 		return NT_STATUS_INVALID_PARAMETER;
235 	}
236 
237 	return gensec_unwrap(gensec_security->child_security,
238 			     mem_ctx, in, out);
239 }
240 
gensec_child_sig_size(struct gensec_security * gensec_security,size_t data_size)241 size_t gensec_child_sig_size(struct gensec_security *gensec_security,
242 			     size_t data_size)
243 {
244 	if (gensec_security->child_security == NULL) {
245 		return 0;
246 	}
247 
248 	return gensec_sig_size(gensec_security->child_security, data_size);
249 }
250 
gensec_child_max_input_size(struct gensec_security * gensec_security)251 size_t gensec_child_max_input_size(struct gensec_security *gensec_security)
252 {
253 	if (gensec_security->child_security == NULL) {
254 		return 0;
255 	}
256 
257 	return gensec_max_input_size(gensec_security->child_security);
258 }
259 
gensec_child_max_wrapped_size(struct gensec_security * gensec_security)260 size_t gensec_child_max_wrapped_size(struct gensec_security *gensec_security)
261 {
262 	if (gensec_security->child_security == NULL) {
263 		return 0;
264 	}
265 
266 	return gensec_max_wrapped_size(gensec_security->child_security);
267 }
268 
gensec_child_session_key(struct gensec_security * gensec_security,TALLOC_CTX * mem_ctx,DATA_BLOB * session_key)269 NTSTATUS gensec_child_session_key(struct gensec_security *gensec_security,
270 				  TALLOC_CTX *mem_ctx,
271 				  DATA_BLOB *session_key)
272 {
273 	if (gensec_security->child_security == NULL) {
274 		return NT_STATUS_INVALID_PARAMETER;
275 	}
276 
277 	return gensec_session_key(gensec_security->child_security,
278 				  mem_ctx,
279 				  session_key);
280 }
281 
gensec_child_session_info(struct gensec_security * gensec_security,TALLOC_CTX * mem_ctx,struct auth_session_info ** session_info)282 NTSTATUS gensec_child_session_info(struct gensec_security *gensec_security,
283 				   TALLOC_CTX *mem_ctx,
284 				   struct auth_session_info **session_info)
285 {
286 	if (gensec_security->child_security == NULL) {
287 		return NT_STATUS_INVALID_PARAMETER;
288 	}
289 
290 	return gensec_session_info(gensec_security->child_security,
291 				   mem_ctx,
292 				   session_info);
293 }
294 
gensec_child_expire_time(struct gensec_security * gensec_security)295 NTTIME gensec_child_expire_time(struct gensec_security *gensec_security)
296 {
297 	if (gensec_security->child_security == NULL) {
298 		return GENSEC_EXPIRE_TIME_INFINITY;
299 	}
300 
301 	return gensec_expire_time(gensec_security->child_security);
302 }
303 
gensec_child_final_auth_type(struct gensec_security * gensec_security)304 const char *gensec_child_final_auth_type(struct gensec_security *gensec_security)
305 {
306 	if (gensec_security->child_security == NULL) {
307 		return "NONE";
308 	}
309 
310 	return gensec_final_auth_type(gensec_security->child_security);
311 }
312