| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  linux/net/sunrpc/gss_mech_switch.c | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  Copyright (c) 2001 The Regents of the University of Michigan. | 
					
						
							|  |  |  |  *  All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  J. Bruce Fields   <bfields@umich.edu> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-02-09 15:38:13 -08:00
										 |  |  |  *  Redistribution and use in source and binary forms, with or without | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  *  modification, are permitted provided that the following conditions | 
					
						
							|  |  |  |  *  are met: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  1. Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |  *     notice, this list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  *  2. Redistributions in binary form must reproduce the above copyright | 
					
						
							| 
									
										
										
										
											2007-02-09 15:38:13 -08:00
										 |  |  |  *     notice, this list of conditions and the following disclaimer in the | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  *     documentation and/or other materials provided with the distribution. | 
					
						
							|  |  |  |  *  3. Neither the name of the University nor the names of its | 
					
						
							|  |  |  |  *     contributors may be used to endorse or promote products derived | 
					
						
							|  |  |  |  *     from this software without specific prior written permission. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | 
					
						
							|  |  |  |  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 
					
						
							|  |  |  |  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
					
						
							|  |  |  |  *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 
					
						
							|  |  |  |  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 
					
						
							|  |  |  |  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 
					
						
							|  |  |  |  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | 
					
						
							|  |  |  |  *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 
					
						
							|  |  |  |  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
					
						
							|  |  |  |  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
					
						
							|  |  |  |  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/types.h>
 | 
					
						
							|  |  |  | #include <linux/slab.h>
 | 
					
						
							|  |  |  | #include <linux/module.h>
 | 
					
						
							| 
									
										
										
										
											2013-03-16 15:54:52 -04:00
										 |  |  | #include <linux/oid_registry.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <linux/sunrpc/msg_prot.h>
 | 
					
						
							|  |  |  | #include <linux/sunrpc/gss_asn1.h>
 | 
					
						
							|  |  |  | #include <linux/sunrpc/auth_gss.h>
 | 
					
						
							|  |  |  | #include <linux/sunrpc/svcauth_gss.h>
 | 
					
						
							|  |  |  | #include <linux/sunrpc/gss_err.h>
 | 
					
						
							|  |  |  | #include <linux/sunrpc/sched.h>
 | 
					
						
							|  |  |  | #include <linux/sunrpc/gss_api.h>
 | 
					
						
							|  |  |  | #include <linux/sunrpc/clnt.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef RPC_DEBUG
 | 
					
						
							|  |  |  | # define RPCDBG_FACILITY        RPCDBG_AUTH
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static LIST_HEAD(registered_mechs); | 
					
						
							|  |  |  | static DEFINE_SPINLOCK(registered_mechs_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | gss_mech_free(struct gss_api_mech *gm) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct pf_desc *pf; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < gm->gm_pf_num; i++) { | 
					
						
							|  |  |  | 		pf = &gm->gm_pfs[i]; | 
					
						
							| 
									
										
										
										
											2005-11-08 09:41:34 -08:00
										 |  |  | 		kfree(pf->auth_domain_name); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		pf->auth_domain_name = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline char * | 
					
						
							|  |  |  | make_auth_domain_name(char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	static char	*prefix = "gss/"; | 
					
						
							|  |  |  | 	char		*new; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	new = kmalloc(strlen(name) + strlen(prefix) + 1, GFP_KERNEL); | 
					
						
							|  |  |  | 	if (new) { | 
					
						
							|  |  |  | 		strcpy(new, prefix); | 
					
						
							|  |  |  | 		strcat(new, name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return new; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | gss_mech_svc_setup(struct gss_api_mech *gm) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct pf_desc *pf; | 
					
						
							|  |  |  | 	int i, status; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < gm->gm_pf_num; i++) { | 
					
						
							|  |  |  | 		pf = &gm->gm_pfs[i]; | 
					
						
							|  |  |  | 		pf->auth_domain_name = make_auth_domain_name(pf->name); | 
					
						
							|  |  |  | 		status = -ENOMEM; | 
					
						
							|  |  |  | 		if (pf->auth_domain_name == NULL) | 
					
						
							|  |  |  | 			goto out; | 
					
						
							|  |  |  | 		status = svcauth_gss_register_pseudoflavor(pf->pseudoflavor, | 
					
						
							|  |  |  | 							pf->auth_domain_name); | 
					
						
							|  |  |  | 		if (status) | 
					
						
							|  |  |  | 			goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	gss_mech_free(gm); | 
					
						
							|  |  |  | 	return status; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-16 15:55:27 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * gss_mech_register - register a GSS mechanism | 
					
						
							|  |  |  |  * @gm: GSS mechanism handle | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns zero if successful, or a negative errno. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int gss_mech_register(struct gss_api_mech *gm) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int status; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	status = gss_mech_svc_setup(gm); | 
					
						
							|  |  |  | 	if (status) | 
					
						
							|  |  |  | 		return status; | 
					
						
							|  |  |  | 	spin_lock(®istered_mechs_lock); | 
					
						
							|  |  |  | 	list_add(&gm->gm_list, ®istered_mechs); | 
					
						
							|  |  |  | 	spin_unlock(®istered_mechs_lock); | 
					
						
							| 
									
										
										
										
											2007-01-31 12:14:05 -05:00
										 |  |  | 	dprintk("RPC:       registered gss mechanism %s\n", gm->gm_name); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-23 15:21:32 -05:00
										 |  |  | EXPORT_SYMBOL_GPL(gss_mech_register); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-16 15:55:27 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * gss_mech_unregister - release a GSS mechanism | 
					
						
							|  |  |  |  * @gm: GSS mechanism handle | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void gss_mech_unregister(struct gss_api_mech *gm) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	spin_lock(®istered_mechs_lock); | 
					
						
							|  |  |  | 	list_del(&gm->gm_list); | 
					
						
							|  |  |  | 	spin_unlock(®istered_mechs_lock); | 
					
						
							| 
									
										
										
										
											2007-01-31 12:14:05 -05:00
										 |  |  | 	dprintk("RPC:       unregistered gss mechanism %s\n", gm->gm_name); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	gss_mech_free(gm); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-23 15:21:32 -05:00
										 |  |  | EXPORT_SYMBOL_GPL(gss_mech_unregister); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-14 16:07:13 -04:00
										 |  |  | struct gss_api_mech *gss_mech_get(struct gss_api_mech *gm) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	__module_get(gm->gm_owner); | 
					
						
							|  |  |  | 	return gm; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-05-14 16:07:13 -04:00
										 |  |  | EXPORT_SYMBOL(gss_mech_get); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-12 11:17:14 -05:00
										 |  |  | static struct gss_api_mech * | 
					
						
							| 
									
										
										
										
											2011-06-22 10:50:08 -04:00
										 |  |  | _gss_mech_get_by_name(const char *name) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct gss_api_mech	*pos, *gm = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	spin_lock(®istered_mechs_lock); | 
					
						
							|  |  |  | 	list_for_each_entry(pos, ®istered_mechs, gm_list) { | 
					
						
							|  |  |  | 		if (0 == strcmp(name, pos->gm_name)) { | 
					
						
							|  |  |  | 			if (try_module_get(pos->gm_owner)) | 
					
						
							|  |  |  | 				gm = pos; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	spin_unlock(®istered_mechs_lock); | 
					
						
							|  |  |  | 	return gm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-22 10:50:08 -04:00
										 |  |  | struct gss_api_mech * gss_mech_get_by_name(const char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct gss_api_mech *gm = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gm = _gss_mech_get_by_name(name); | 
					
						
							|  |  |  | 	if (!gm) { | 
					
						
							|  |  |  | 		request_module("rpc-auth-gss-%s", name); | 
					
						
							|  |  |  | 		gm = _gss_mech_get_by_name(name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return gm; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-29 14:03:30 -04:00
										 |  |  | struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj) | 
					
						
							| 
									
										
										
										
											2011-03-24 17:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct gss_api_mech	*pos, *gm = NULL; | 
					
						
							| 
									
										
										
										
											2013-03-16 15:54:52 -04:00
										 |  |  | 	char buf[32]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (sprint_oid(obj->data, obj->len, buf, sizeof(buf)) < 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	dprintk("RPC:       %s(%s)\n", __func__, buf); | 
					
						
							|  |  |  | 	request_module("rpc-auth-gss-%s", buf); | 
					
						
							| 
									
										
										
										
											2011-03-24 17:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	spin_lock(®istered_mechs_lock); | 
					
						
							|  |  |  | 	list_for_each_entry(pos, ®istered_mechs, gm_list) { | 
					
						
							|  |  |  | 		if (obj->len == pos->gm_oid.len) { | 
					
						
							|  |  |  | 			if (0 == memcmp(obj->data, pos->gm_oid.data, obj->len)) { | 
					
						
							|  |  |  | 				if (try_module_get(pos->gm_owner)) | 
					
						
							|  |  |  | 					gm = pos; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	spin_unlock(®istered_mechs_lock); | 
					
						
							|  |  |  | 	return gm; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | static inline int | 
					
						
							|  |  |  | mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < gm->gm_pf_num; i++) { | 
					
						
							|  |  |  | 		if (gm->gm_pfs[i].pseudoflavor == pseudoflavor) | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-12 11:17:14 -05:00
										 |  |  | static struct gss_api_mech *_gss_mech_get_by_pseudoflavor(u32 pseudoflavor) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-22 10:50:08 -04:00
										 |  |  | 	struct gss_api_mech *gm = NULL, *pos; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	spin_lock(®istered_mechs_lock); | 
					
						
							|  |  |  | 	list_for_each_entry(pos, ®istered_mechs, gm_list) { | 
					
						
							| 
									
										
										
										
											2014-05-18 13:47:14 -04:00
										 |  |  | 		if (!mech_supports_pseudoflavor(pos, pseudoflavor)) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			continue; | 
					
						
							|  |  |  | 		if (try_module_get(pos->gm_owner)) | 
					
						
							|  |  |  | 			gm = pos; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	spin_unlock(®istered_mechs_lock); | 
					
						
							|  |  |  | 	return gm; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-22 10:50:08 -04:00
										 |  |  | struct gss_api_mech * | 
					
						
							|  |  |  | gss_mech_get_by_pseudoflavor(u32 pseudoflavor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct gss_api_mech *gm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gm = _gss_mech_get_by_pseudoflavor(pseudoflavor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!gm) { | 
					
						
							|  |  |  | 		request_module("rpc-auth-gss-%u", pseudoflavor); | 
					
						
							|  |  |  | 		gm = _gss_mech_get_by_pseudoflavor(pseudoflavor); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return gm; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-11 16:31:08 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors | 
					
						
							|  |  |  |  * @array: array to fill in | 
					
						
							|  |  |  |  * @size: size of "array" | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns the number of array items filled in, or a negative errno. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The returned array is not sorted by any policy.  Callers should not | 
					
						
							|  |  |  |  * rely on the order of the items in the returned array. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr, int size) | 
					
						
							| 
									
										
										
										
											2011-03-24 17:12:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct gss_api_mech *pos = NULL; | 
					
						
							| 
									
										
										
										
											2012-05-03 11:47:08 -04:00
										 |  |  | 	int j, i = 0; | 
					
						
							| 
									
										
										
										
											2011-03-24 17:12:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	spin_lock(®istered_mechs_lock); | 
					
						
							|  |  |  | 	list_for_each_entry(pos, ®istered_mechs, gm_list) { | 
					
						
							| 
									
										
										
										
											2012-07-11 16:31:08 -04:00
										 |  |  | 		for (j = 0; j < pos->gm_pf_num; j++) { | 
					
						
							| 
									
										
										
										
											2012-07-17 14:47:30 -04:00
										 |  |  | 			if (i >= size) { | 
					
						
							|  |  |  | 				spin_unlock(®istered_mechs_lock); | 
					
						
							| 
									
										
										
										
											2012-07-11 16:31:08 -04:00
										 |  |  | 				return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2012-07-17 14:47:30 -04:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-05-03 11:47:08 -04:00
										 |  |  | 			array_ptr[i++] = pos->gm_pfs[j].pseudoflavor; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-03-24 17:12:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	spin_unlock(®istered_mechs_lock); | 
					
						
							|  |  |  | 	return i; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-16 15:55:01 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * gss_svc_to_pseudoflavor - map a GSS service number to a pseudoflavor | 
					
						
							|  |  |  |  * @gm: GSS mechanism handle | 
					
						
							|  |  |  |  * @qop: GSS quality-of-protection value | 
					
						
							|  |  |  |  * @service: GSS service value | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns a matching security flavor, or RPC_AUTH_MAXFLAVOR if none is found. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | rpc_authflavor_t gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 qop, | 
					
						
							|  |  |  | 					 u32 service) | 
					
						
							| 
									
										
										
										
											2007-07-17 04:04:42 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < gm->gm_pf_num; i++) { | 
					
						
							| 
									
										
										
										
											2013-03-16 15:55:01 -04:00
										 |  |  | 		if (gm->gm_pfs[i].qop == qop && | 
					
						
							|  |  |  | 		    gm->gm_pfs[i].service == service) { | 
					
						
							| 
									
										
										
										
											2007-07-17 04:04:42 -07:00
										 |  |  | 			return gm->gm_pfs[i].pseudoflavor; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-03-16 15:55:01 -04:00
										 |  |  | 	return RPC_AUTH_MAXFLAVOR; | 
					
						
							| 
									
										
										
										
											2007-07-17 04:04:42 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-16 15:54:43 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * gss_mech_info2flavor - look up a pseudoflavor given a GSS tuple | 
					
						
							|  |  |  |  * @info: a GSS mech OID, quality of protection, and service value | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns a matching pseudoflavor, or RPC_AUTH_MAXFLAVOR if the tuple is | 
					
						
							|  |  |  |  * not supported. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *info) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	rpc_authflavor_t pseudoflavor; | 
					
						
							|  |  |  | 	struct gss_api_mech *gm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gm = gss_mech_get_by_OID(&info->oid); | 
					
						
							|  |  |  | 	if (gm == NULL) | 
					
						
							|  |  |  | 		return RPC_AUTH_MAXFLAVOR; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-16 15:55:01 -04:00
										 |  |  | 	pseudoflavor = gss_svc_to_pseudoflavor(gm, info->qop, info->service); | 
					
						
							| 
									
										
										
										
											2013-03-16 15:54:43 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	gss_mech_put(gm); | 
					
						
							|  |  |  | 	return pseudoflavor; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-16 15:55:10 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * gss_mech_flavor2info - look up a GSS tuple for a given pseudoflavor | 
					
						
							|  |  |  |  * @pseudoflavor: GSS pseudoflavor to match | 
					
						
							|  |  |  |  * @info: rpcsec_gss_info structure to fill in | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns zero and fills in "info" if pseudoflavor matches a | 
					
						
							|  |  |  |  * supported mechanism.  Otherwise a negative errno is returned. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int gss_mech_flavor2info(rpc_authflavor_t pseudoflavor, | 
					
						
							|  |  |  | 			 struct rpcsec_gss_info *info) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct gss_api_mech *gm; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gm = gss_mech_get_by_pseudoflavor(pseudoflavor); | 
					
						
							|  |  |  | 	if (gm == NULL) | 
					
						
							|  |  |  | 		return -ENOENT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < gm->gm_pf_num; i++) { | 
					
						
							|  |  |  | 		if (gm->gm_pfs[i].pseudoflavor == pseudoflavor) { | 
					
						
							|  |  |  | 			memcpy(info->oid.data, gm->gm_oid.data, gm->gm_oid.len); | 
					
						
							|  |  |  | 			info->oid.len = gm->gm_oid.len; | 
					
						
							|  |  |  | 			info->qop = gm->gm_pfs[i].qop; | 
					
						
							|  |  |  | 			info->service = gm->gm_pfs[i].service; | 
					
						
							|  |  |  | 			gss_mech_put(gm); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gss_mech_put(gm); | 
					
						
							|  |  |  | 	return -ENOENT; | 
					
						
							| 
									
										
										
										
											2007-07-17 04:04:42 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | u32 | 
					
						
							|  |  |  | gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < gm->gm_pf_num; i++) { | 
					
						
							|  |  |  | 		if (gm->gm_pfs[i].pseudoflavor == pseudoflavor) | 
					
						
							|  |  |  | 			return gm->gm_pfs[i].service; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-05-14 16:07:13 -04:00
										 |  |  | EXPORT_SYMBOL(gss_pseudoflavor_to_service); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < gm->gm_pf_num; i++) { | 
					
						
							|  |  |  | 		if (gm->gm_pfs[i].service == service) | 
					
						
							|  |  |  | 			return gm->gm_pfs[i].auth_domain_name; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | gss_mech_put(struct gss_api_mech * gm) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-30 01:56:16 -07:00
										 |  |  | 	if (gm) | 
					
						
							|  |  |  | 		module_put(gm->gm_owner); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-05-14 16:07:13 -04:00
										 |  |  | EXPORT_SYMBOL(gss_mech_put); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* The mech could probably be determined from the token instead, but it's just
 | 
					
						
							|  |  |  |  * as easy for now to pass it in. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | gss_import_sec_context(const void *input_token, size_t bufsize, | 
					
						
							|  |  |  | 		       struct gss_api_mech	*mech, | 
					
						
							| 
									
										
										
										
											2010-05-13 12:51:02 -04:00
										 |  |  | 		       struct gss_ctx		**ctx_id, | 
					
						
							| 
									
										
										
										
											2012-05-25 18:09:53 -04:00
										 |  |  | 		       time_t			*endtime, | 
					
						
							| 
									
										
										
										
											2010-05-13 12:51:02 -04:00
										 |  |  | 		       gfp_t gfp_mask) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-13 12:51:02 -04:00
										 |  |  | 	if (!(*ctx_id = kzalloc(sizeof(**ctx_id), gfp_mask))) | 
					
						
							| 
									
										
										
										
											2009-12-18 16:28:12 -05:00
										 |  |  | 		return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	(*ctx_id)->mech_type = gss_mech_get(mech); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-25 18:09:53 -04:00
										 |  |  | 	return mech->gm_ops->gss_import_sec_context(input_token, bufsize, | 
					
						
							|  |  |  | 						*ctx_id, endtime, gfp_mask); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* gss_get_mic: compute a mic over message and return mic_token. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u32 | 
					
						
							|  |  |  | gss_get_mic(struct gss_ctx	*context_handle, | 
					
						
							|  |  |  | 	    struct xdr_buf	*message, | 
					
						
							|  |  |  | 	    struct xdr_netobj	*mic_token) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	 return context_handle->mech_type->gm_ops | 
					
						
							|  |  |  | 		->gss_get_mic(context_handle, | 
					
						
							|  |  |  | 			      message, | 
					
						
							|  |  |  | 			      mic_token); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* gss_verify_mic: check whether the provided mic_token verifies message. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u32 | 
					
						
							|  |  |  | gss_verify_mic(struct gss_ctx		*context_handle, | 
					
						
							|  |  |  | 	       struct xdr_buf		*message, | 
					
						
							| 
									
										
										
										
											2005-10-13 16:55:18 -04:00
										 |  |  | 	       struct xdr_netobj	*mic_token) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	return context_handle->mech_type->gm_ops | 
					
						
							|  |  |  | 		->gss_verify_mic(context_handle, | 
					
						
							|  |  |  | 				 message, | 
					
						
							| 
									
										
										
										
											2005-10-13 16:55:18 -04:00
										 |  |  | 				 mic_token); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-17 13:02:47 -04:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This function is called from both the client and server code. | 
					
						
							|  |  |  |  * Each makes guarantees about how much "slack" space is available | 
					
						
							|  |  |  |  * for the underlying function in "buf"'s head and tail while | 
					
						
							|  |  |  |  * performing the wrap. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The client and server code allocate RPC_MAX_AUTH_SIZE extra | 
					
						
							|  |  |  |  * space in both the head and tail which is available for use by | 
					
						
							|  |  |  |  * the wrap function. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Underlying functions should verify they do not use more than | 
					
						
							|  |  |  |  * RPC_MAX_AUTH_SIZE of extra space in either the head or tail | 
					
						
							|  |  |  |  * when performing the wrap. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2005-10-13 16:54:37 -04:00
										 |  |  | u32 | 
					
						
							|  |  |  | gss_wrap(struct gss_ctx	*ctx_id, | 
					
						
							|  |  |  | 	 int		offset, | 
					
						
							|  |  |  | 	 struct xdr_buf	*buf, | 
					
						
							|  |  |  | 	 struct page	**inpages) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ctx_id->mech_type->gm_ops | 
					
						
							| 
									
										
										
										
											2005-10-13 16:55:18 -04:00
										 |  |  | 		->gss_wrap(ctx_id, offset, buf, inpages); | 
					
						
							| 
									
										
										
										
											2005-10-13 16:54:37 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u32 | 
					
						
							|  |  |  | gss_unwrap(struct gss_ctx	*ctx_id, | 
					
						
							|  |  |  | 	   int			offset, | 
					
						
							|  |  |  | 	   struct xdr_buf	*buf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ctx_id->mech_type->gm_ops | 
					
						
							| 
									
										
										
										
											2005-10-13 16:55:18 -04:00
										 |  |  | 		->gss_unwrap(ctx_id, offset, buf); | 
					
						
							| 
									
										
										
										
											2005-10-13 16:54:37 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* gss_delete_sec_context: free all resources associated with context_handle.
 | 
					
						
							|  |  |  |  * Note this differs from the RFC 2744-specified prototype in that we don't | 
					
						
							|  |  |  |  * bother returning an output token, since it would never be used anyway. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u32 | 
					
						
							|  |  |  | gss_delete_sec_context(struct gss_ctx	**context_handle) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-01-31 12:14:05 -05:00
										 |  |  | 	dprintk("RPC:       gss_delete_sec_context deleting %p\n", | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			*context_handle); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!*context_handle) | 
					
						
							| 
									
										
										
										
											2010-09-22 20:43:57 +00:00
										 |  |  | 		return GSS_S_NO_CONTEXT; | 
					
						
							| 
									
										
										
										
											2008-03-17 22:48:03 -07:00
										 |  |  | 	if ((*context_handle)->internal_ctx_id) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		(*context_handle)->mech_type->gm_ops | 
					
						
							|  |  |  | 			->gss_delete_sec_context((*context_handle) | 
					
						
							|  |  |  | 							->internal_ctx_id); | 
					
						
							| 
									
										
										
										
											2006-06-30 01:56:16 -07:00
										 |  |  | 	gss_mech_put((*context_handle)->mech_type); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	kfree(*context_handle); | 
					
						
							|  |  |  | 	*context_handle=NULL; | 
					
						
							|  |  |  | 	return GSS_S_COMPLETE; | 
					
						
							|  |  |  | } |