diff -u -r -N linux-2.5.49-02-auth2/fs/Kconfig linux-2.5.49-03-rpc_gss/fs/Kconfig --- linux-2.5.49-02-auth2/fs/Kconfig 2002-11-24 00:39:54.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/fs/Kconfig 2002-11-24 00:51:19.000000000 -0500 @@ -1339,6 +1339,14 @@ default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m) default y if NFS_FS=y || NFSD=y +config SUNRPC_GSS + tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)" + depends on SUNRPC && EXPERIMENTAL + help + Provides cryptographic authentication for NFS rpc requests. To + make this useful, you also need support for a gss-api mechanism + (such as Kerberos). + config LOCKD tristate default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m) diff -u -r -N linux-2.5.49-02-auth2/fs/nfs/inode.c linux-2.5.49-03-rpc_gss/fs/nfs/inode.c --- linux-2.5.49-02-auth2/fs/nfs/inode.c 2002-11-24 00:39:55.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/fs/nfs/inode.c 2002-11-24 00:51:19.000000000 -0500 @@ -345,6 +345,7 @@ struct rpc_clnt *clnt = NULL; struct rpc_timeout timeparms; int tcp, err = -EIO; + u32 authflavor; server = NFS_SB(sb); sb->s_blocksize_bits = 0; @@ -407,8 +408,14 @@ printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); goto out_fail; } + + if (data->flags & NFS_MOUNT_SECFLAVOUR) + authflavor = data->pseudoflavor; + else + authflavor = RPC_AUTH_UNIX; + clnt = rpc_create_client(xprt, server->hostname, &nfs_program, - server->rpc_ops->version, RPC_AUTH_UNIX); + server->rpc_ops->version, authflavor); if (clnt == NULL) { printk(KERN_WARNING "NFS: cannot create RPC client.\n"); xprt_destroy(xprt); @@ -1190,6 +1197,7 @@ struct nfs_fh *root; struct nfs_mount_data *data = raw_data; + printk("XXXJBF: data->pseudoflavor = %d\n", data->pseudoflavor); if (!data) { printk("nfs_read_super: missing data argument\n"); return ERR_PTR(-EINVAL); diff -u -r -N linux-2.5.49-02-auth2/include/linux/nfs_mount.h linux-2.5.49-03-rpc_gss/include/linux/nfs_mount.h --- linux-2.5.49-02-auth2/include/linux/nfs_mount.h 2002-10-19 00:01:08.000000000 -0400 +++ linux-2.5.49-03-rpc_gss/include/linux/nfs_mount.h 2002-11-24 00:51:19.000000000 -0500 @@ -40,6 +40,7 @@ int namlen; /* 2 */ unsigned int bsize; /* 3 */ struct nfs3_fh root; /* 4 */ + int pseudoflavor; /* 4 */ }; /* bits in the flags field */ @@ -55,10 +56,8 @@ #define NFS_MOUNT_KERBEROS 0x0100 /* 3 */ #define NFS_MOUNT_NONLM 0x0200 /* 3 */ #define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */ -#if 0 #define NFS_MOUNT_STRICTLOCK 0x1000 /* reserved for NFSv4 */ #define NFS_MOUNT_SECFLAVOUR 0x2000 /* reserved */ -#endif #define NFS_MOUNT_FLAGMASK 0xFFFF #endif diff -u -r -N linux-2.5.49-02-auth2/include/linux/sunrpc/auth.h linux-2.5.49-03-rpc_gss/include/linux/sunrpc/auth.h --- linux-2.5.49-02-auth2/include/linux/sunrpc/auth.h 2002-11-24 00:51:16.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/include/linux/sunrpc/auth.h 2002-11-24 00:51:19.000000000 -0500 @@ -13,12 +13,17 @@ #include #include +#include +#include #include /* size of the nodename buffer */ #define UNX_MAXNODENAME 32 +/* Maximum size (in bytes) of an rpc credential or verifier */ +#define RPC_MAX_AUTH_SIZE (400) + /* Work around the lack of a VFS credential */ struct auth_cred { uid_t uid; @@ -64,6 +69,10 @@ unsigned int au_rslack; /* reply verf size guess */ unsigned int au_flags; /* various flags */ struct rpc_authops * au_ops; /* operations */ + rpc_authflavor_t au_flavor; /* pseudoflavor (note may + * differ from the flavor in + * au_ops->au_flavor in gss + * case) */ /* per-flavor data */ }; @@ -79,10 +88,10 @@ #ifdef RPC_DEBUG char * au_name; #endif - struct rpc_auth * (*create)(struct rpc_clnt *); + struct rpc_auth * (*create)(struct rpc_clnt *, rpc_authflavor_t); void (*destroy)(struct rpc_auth *); - struct rpc_cred * (*crcreate)(struct auth_cred *, int); + struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int); }; struct rpc_credops { @@ -100,6 +109,8 @@ extern struct rpc_authops authdes_ops; #endif +u32 pseudoflavor_to_flavor(rpc_authflavor_t); + int rpcauth_register(struct rpc_authops *); int rpcauth_unregister(struct rpc_authops *); struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); diff -u -r -N linux-2.5.49-02-auth2/include/linux/sunrpc/auth_gss.h linux-2.5.49-03-rpc_gss/include/linux/sunrpc/auth_gss.h --- linux-2.5.49-02-auth2/include/linux/sunrpc/auth_gss.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/include/linux/sunrpc/auth_gss.h 2002-11-24 00:51:19.000000000 -0500 @@ -0,0 +1,97 @@ +/* + * linux/include/linux/auth_gss.h + * + * Declarations for RPCSEC_GSS + * + * Dug Song + * Andy Adamson + * Bruce Fields + * Copyright (c) 2000 The Regents of the University of Michigan + * + * $Id$ + */ + +#ifndef _LINUX_SUNRPC_AUTH_GSS_H +#define _LINUX_SUNRPC_AUTH_GSS_H + +#ifdef __KERNEL__ +#ifdef __linux__ +#include +#include +#include +#endif + +#define RPC_GSS_VERSION 1 + +#define MAXSEQ 0x80000000 /* maximum legal sequence number, from rfc 2203 */ + +enum rpc_gss_proc { + RPC_GSS_PROC_DATA = 0, + RPC_GSS_PROC_INIT = 1, + RPC_GSS_PROC_CONTINUE_INIT = 2, + RPC_GSS_PROC_DESTROY = 3 +}; + +enum rpc_gss_svc { + RPC_GSS_SVC_NONE = 1, + RPC_GSS_SVC_INTEGRITY = 2, + RPC_GSS_SVC_PRIVACY = 3 +}; + +/* on-the-wire gss cred: */ +struct rpc_gss_wire_cred { + u32 gc_v; /* version */ + u32 gc_proc; /* control procedure */ + u32 gc_seq; /* sequence number */ + u32 gc_svc; /* service */ + struct xdr_netobj gc_ctx; /* context handle */ +}; + +/* on-the-wire gss verifier: */ +struct rpc_gss_wire_verf { + u32 gv_flavor; + struct xdr_netobj gv_verf; +}; + +/* return from gss NULL PROC init sec context */ +struct rpc_gss_init_res { + struct xdr_netobj gr_ctx; /* context handle */ + u32 gr_major; /* major status */ + u32 gr_minor; /* minor status */ + u32 gr_win; /* sequence window */ + struct xdr_netobj gr_token; /* token */ +}; + +#define GSS_SEQ_WIN 5 + +/* The gss_cl_ctx struct holds all the information the rpcsec_gss client + * code needs to know about a single security context. In particular, + * gc_gss_ctx is the context handle that is used to do gss-api calls, while + * gc_wire_ctx is the context handle that is used to identify the context on + * the wire when communicating with a server. */ + +struct gss_cl_ctx { + u32 gc_proc; + u32 gc_seq; + spinlock_t gc_seq_lock; + struct gss_ctx *gc_gss_ctx; + struct xdr_netobj gc_wire_ctx; + u32 gc_win; +}; + +struct gss_cred { + struct rpc_cred gc_base; + u32 gc_flavor; + struct gss_cl_ctx *gc_ctx; +}; + +#define gc_uid gc_base.cr_uid +#define gc_count gc_base.cr_count +#define gc_flags gc_base.cr_flags +#define gc_expire gc_base.cr_expire + +void print_hexl(u32 *p, u_int length, u_int offset); + +#endif /* __KERNEL__ */ +#endif /* _LINUX_SUNRPC_AUTH_GSS_H */ + diff -u -r -N linux-2.5.49-02-auth2/include/linux/sunrpc/gss_api.h linux-2.5.49-03-rpc_gss/include/linux/sunrpc/gss_api.h --- linux-2.5.49-02-auth2/include/linux/sunrpc/gss_api.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/include/linux/sunrpc/gss_api.h 2002-11-24 00:51:19.000000000 -0500 @@ -0,0 +1,145 @@ +/* + * linux/include/linux/gss_api.h + * + * Somewhat simplified version of the gss api. + * + * Dug Song + * Andy Adamson + * Bruce Fields + * Copyright (c) 2000 The Regents of the University of Michigan + * + * $Id$ + */ + +#ifndef _LINUX_SUNRPC_GSS_API_H +#define _LINUX_SUNRPC_GSS_API_H + +#ifdef __KERNEL__ +#include + +/* The mechanism-independent gss-api context: */ +struct gss_ctx { + struct gss_api_mech *mech_type; + void *internal_ctx_id; +}; + +#define GSS_C_NO_BUFFER ((struct xdr_netobj) 0) +#define GSS_C_NO_CONTEXT ((struct gss_ctx *) 0) +#define GSS_C_NULL_OID ((struct xdr_netobj) 0) + +/*XXX arbitrary length - is this set somewhere? */ +#define GSS_OID_MAX_LEN 32 + +/* gss-api prototypes; note that these are somewhat simplified versions of + * the prototypes specified in RFC 2744. */ +u32 gss_accept_sec_context( + struct gss_ctx **ctx_id, + struct xdr_netobj *input_token, + uid_t *initiator_uid, + struct xdr_netobj *output_token, + u32 *ret_flags); +u32 gss_import_sec_context( + struct xdr_netobj *input_token, + struct gss_api_mech *mech, + struct gss_ctx **ctx_id); +u32 gss_get_mic( + struct gss_ctx *ctx_id, + u32 qop, + struct xdr_netobj *message_buffer, + struct xdr_netobj *message_token); +u32 gss_verify_mic( + struct gss_ctx *ctx_id, + struct xdr_netobj *signbuf, + struct xdr_netobj *checksum, + u32 *qstate); +u32 gss_delete_sec_context( + struct gss_ctx **ctx_id); + +/* We maintain a list of the pseudoflavors (equivalently, mechanism-qop-service + * triples) that we currently support: */ + +struct sup_sec_triple { + struct list_head triples; + u32 pseudoflavor; + struct gss_api_mech *mech; + u32 qop; + u32 service; +}; + +int gss_register_triple(u32 pseudoflavor, struct gss_api_mech *mech, u32 qop, + u32 service); +int gss_unregister_triple(u32 pseudoflavor); +int gss_pseudoflavor_supported(u32 pseudoflavor); +u32 gss_cmp_triples(u32 oid_len, char *oid_data, u32 qop, u32 service); +u32 gss_get_pseudoflavor(struct gss_ctx *ctx_id, u32 qop, u32 service); +u32 gss_pseudoflavor_to_service(u32 pseudoflavor); +/* Both return NULL on failure: */ +struct gss_api_mech * gss_pseudoflavor_to_mech(u32 pseudoflavor); +int gss_pseudoflavor_to_mechOID(u32 pseudoflavor, struct xdr_netobj *mech); + +/* Different mechanisms (e.g., krb5 or spkm3) may implement gss-api, and + * mechanisms may be dynamically registered or unregistered by modules. + * Our only built-in mechanism is a trivial debugging mechanism that provides + * no actual security; the following function registers that mechanism: */ + +void gss_mech_register_debug(void); + +/* Each mechanism is described by the following struct: */ +struct gss_api_mech { + struct xdr_netobj gm_oid; + struct list_head gm_list; + atomic_t gm_count; + struct gss_api_ops *gm_ops; +}; + +/* and must provide the following operations: */ +struct gss_api_ops { + char *name; + u32 (*gss_accept_sec_context)( + /* Note memory for the ctx_id is allocated by caller */ + struct gss_ctx *ctx_id, + struct xdr_netobj *input_token, + struct xdr_netobj *client_name, + struct xdr_netobj *output_token, + u32 *ret_flags); + u32 (*gss_import_sec_context)( + struct xdr_netobj *input_token, + struct gss_ctx *ctx_id); + u32 (*gss_get_mic)( + struct gss_ctx *ctx_id, + u32 qop, + struct xdr_netobj *message_buffer, + struct xdr_netobj *message_token); + u32 (*gss_verify_mic)( + struct gss_ctx *ctx_id, + struct xdr_netobj *signbuf, + struct xdr_netobj *checksum, + u32 *qstate); + void (*gss_delete_sec_context)( + void *internal_ctx_id); +}; + +/* Returns nonzero on failure. */ +int gss_mech_register(struct xdr_netobj *, struct gss_api_ops *); + +/* Returns nonzero iff someone still has a reference to this mech. */ +int gss_mech_unregister(struct gss_api_mech *); + +/* Returns nonzer iff someone still has a reference to some mech. */ +int gss_mech_unregister_all(void); + +/* returns a mechanism descriptor given an OID, an increments the mechanism's + * reference count. */ +struct gss_api_mech * gss_mech_get_by_OID(struct xdr_netobj *); + +/* Just increments the mechanism's reference count and returns its input: */ +struct gss_api_mech * gss_mech_get(struct gss_api_mech *); + +/* Returns nonzero iff you've released the last reference to this mech. + * Note that for every succesful gss_get_mech call there must be exactly + * one corresponding call to gss_mech_put.*/ +int gss_mech_put(struct gss_api_mech *); + +#endif /* __KERNEL__ */ +#endif /* _LINUX_SUNRPC_GSS_API_H */ + diff -u -r -N linux-2.5.49-02-auth2/include/linux/sunrpc/gss_asn1.h linux-2.5.49-03-rpc_gss/include/linux/sunrpc/gss_asn1.h --- linux-2.5.49-02-auth2/include/linux/sunrpc/gss_asn1.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/include/linux/sunrpc/gss_asn1.h 2002-11-24 00:51:19.000000000 -0500 @@ -0,0 +1,85 @@ +/* + * linux/include/linux/sunrpc/gss_asn1.h + * + * minimal asn1 for generic encoding/decoding of gss tokens + * + * Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h, + * lib/gssapi/krb5/gssapiP_krb5.h, and others + * + * Copyright (c) 2000 The Regents of the University of Michigan. + * All rights reserved. + * + * Andy Adamson + */ + +/* + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + + +#include + +#define SIZEOF_INT 4 + +/* from gssapi_err_generic.h */ +#define G_BAD_SERVICE_NAME (-2045022976L) +#define G_BAD_STRING_UID (-2045022975L) +#define G_NOUSER (-2045022974L) +#define G_VALIDATE_FAILED (-2045022973L) +#define G_BUFFER_ALLOC (-2045022972L) +#define G_BAD_MSG_CTX (-2045022971L) +#define G_WRONG_SIZE (-2045022970L) +#define G_BAD_USAGE (-2045022969L) +#define G_UNKNOWN_QOP (-2045022968L) +#define G_NO_HOSTNAME (-2045022967L) +#define G_BAD_HOSTNAME (-2045022966L) +#define G_WRONG_MECH (-2045022965L) +#define G_BAD_TOK_HEADER (-2045022964L) +#define G_BAD_DIRECTION (-2045022963L) +#define G_TOK_TRUNC (-2045022962L) +#define G_REFLECT (-2045022961L) +#define G_WRONG_TOKID (-2045022960L) + +#define g_OID_equal(o1,o2) \ + (((o1)->len == (o2)->len) && \ + (memcmp((o1)->data,(o2)->data,(int) (o1)->len) == 0)) + +u32 g_verify_token_header( + struct xdr_netobj *mech, + int *body_size, + unsigned char **buf_in, + int tok_type, + int toksize); + +u32 g_get_mech_oid(struct xdr_netobj *mech, struct xdr_netobj * in_buf); + +int g_token_size( + struct xdr_netobj *mech, + unsigned int body_size); + +void g_make_token_header( + struct xdr_netobj *mech, + int body_size, + unsigned char **buf, + int tok_type); diff -u -r -N linux-2.5.49-02-auth2/include/linux/sunrpc/gss_err.h linux-2.5.49-03-rpc_gss/include/linux/sunrpc/gss_err.h --- linux-2.5.49-02-auth2/include/linux/sunrpc/gss_err.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/include/linux/sunrpc/gss_err.h 2002-11-24 00:51:19.000000000 -0500 @@ -0,0 +1,177 @@ +/* + * linux/include/sunrpc/gss_err.h + * + * Adapted from MIT Kerberos 5-1.2.1 include/gssapi/gssapi.h + * + * Copyright (c) 2002 The Regents of the University of Michigan. + * All rights reserved. + * + * Andy Adamson + */ + +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LINUX_SUNRPC_GSS_ERR_H +#define _LINUX_SUNRPC_GSS_ERR_H + +#ifdef __KERNEL__ + +typedef unsigned int OM_uint32; + +/* + * Flag bits for context-level services. + */ +#define GSS_C_DELEG_FLAG 1 +#define GSS_C_MUTUAL_FLAG 2 +#define GSS_C_REPLAY_FLAG 4 +#define GSS_C_SEQUENCE_FLAG 8 +#define GSS_C_CONF_FLAG 16 +#define GSS_C_INTEG_FLAG 32 +#define GSS_C_ANON_FLAG 64 +#define GSS_C_PROT_READY_FLAG 128 +#define GSS_C_TRANS_FLAG 256 + +/* + * Credential usage options + */ +#define GSS_C_BOTH 0 +#define GSS_C_INITIATE 1 +#define GSS_C_ACCEPT 2 + +/* + * Status code types for gss_display_status + */ +#define GSS_C_GSS_CODE 1 +#define GSS_C_MECH_CODE 2 + + +/* + * Define the default Quality of Protection for per-message services. Note + * that an implementation that offers multiple levels of QOP may either reserve + * a value (for example zero, as assumed here) to mean "default protection", or + * alternatively may simply equate GSS_C_QOP_DEFAULT to a specific explicit + * QOP value. However a value of 0 should always be interpreted by a GSSAPI + * implementation as a request for the default protection level. + */ +#define GSS_C_QOP_DEFAULT 0 + +/* + * Expiration time of 2^32-1 seconds means infinite lifetime for a + * credential or security context + */ +#define GSS_C_INDEFINITE ((OM_uint32) 0xfffffffful) + + +/* Major status codes */ + +#define GSS_S_COMPLETE 0 + +/* + * Some "helper" definitions to make the status code macros obvious. + */ +#define GSS_C_CALLING_ERROR_OFFSET 24 +#define GSS_C_ROUTINE_ERROR_OFFSET 16 +#define GSS_C_SUPPLEMENTARY_OFFSET 0 +#define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul) +#define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul) +#define GSS_C_SUPPLEMENTARY_MASK ((OM_uint32) 0177777ul) + +/* + * The macros that test status codes for error conditions. Note that the + * GSS_ERROR() macro has changed slightly from the V1 GSSAPI so that it now + * evaluates its argument only once. + */ +#define GSS_CALLING_ERROR(x) \ + ((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) +#define GSS_ROUTINE_ERROR(x) \ + ((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) +#define GSS_SUPPLEMENTARY_INFO(x) \ + ((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) +#define GSS_ERROR(x) \ + ((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ + (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) + +/* + * Now the actual status code definitions + */ + +/* + * Calling errors: + */ +#define GSS_S_CALL_INACCESSIBLE_READ \ + (((OM_uint32) 1ul) << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_INACCESSIBLE_WRITE \ + (((OM_uint32) 2ul) << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_BAD_STRUCTURE \ + (((OM_uint32) 3ul) << GSS_C_CALLING_ERROR_OFFSET) + +/* + * Routine errors: + */ +#define GSS_S_BAD_MECH (((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAME (((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAMETYPE (((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_BINDINGS (((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_STATUS (((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_SIG (((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NO_CRED (((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NO_CONTEXT (((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_TOKEN (((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_CREDENTIAL \ + (((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CREDENTIALS_EXPIRED \ + (((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CONTEXT_EXPIRED \ + (((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_FAILURE (((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_QOP (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAUTHORIZED (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAVAILABLE (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DUPLICATE_ELEMENT \ + (((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NAME_NOT_MN \ + (((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET) + +/* + * Supplementary info bits: + */ +#define GSS_S_CONTINUE_NEEDED (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0)) +#define GSS_S_DUPLICATE_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1)) +#define GSS_S_OLD_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2)) +#define GSS_S_UNSEQ_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3)) +#define GSS_S_GAP_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4)) + +/* XXXX these are not part of the GSSAPI C bindings! (but should be) */ + +#define GSS_CALLING_ERROR_FIELD(x) \ + (((x) >> GSS_C_CALLING_ERROR_OFFSET) & GSS_C_CALLING_ERROR_MASK) +#define GSS_ROUTINE_ERROR_FIELD(x) \ + (((x) >> GSS_C_ROUTINE_ERROR_OFFSET) & GSS_C_ROUTINE_ERROR_MASK) +#define GSS_SUPPLEMENTARY_INFO_FIELD(x) \ + (((x) >> GSS_C_SUPPLEMENTARY_OFFSET) & GSS_C_SUPPLEMENTARY_MASK) + +/* XXXX This is a necessary evil until the spec is fixed */ +#define GSS_S_CRED_UNAVAIL GSS_S_FAILURE + +#endif /* __KERNEL__ */ +#endif /* __LINUX_SUNRPC_GSS_ERR_H */ diff -u -r -N linux-2.5.49-02-auth2/include/linux/sunrpc/msg_prot.h linux-2.5.49-03-rpc_gss/include/linux/sunrpc/msg_prot.h --- linux-2.5.49-02-auth2/include/linux/sunrpc/msg_prot.h 2002-10-19 00:02:27.000000000 -0400 +++ linux-2.5.49-03-rpc_gss/include/linux/sunrpc/msg_prot.h 2002-11-24 00:51:19.000000000 -0500 @@ -20,7 +20,18 @@ RPC_AUTH_SHORT = 2, RPC_AUTH_DES = 3, RPC_AUTH_KRB = 4, + RPC_AUTH_GSS = 6, RPC_AUTH_MAXFLAVOR = 8, + /* pseudoflavors: */ + RPC_AUTH_GSS_KRB5 = 390003, + RPC_AUTH_GSS_KRB5I = 390004, + RPC_AUTH_GSS_KRB5P = 390005, + RPC_AUTH_GSS_LKEY = 390006, + RPC_AUTH_GSS_LKEYI = 390007, + RPC_AUTH_GSS_LKEYP = 390008, + RPC_AUTH_GSS_SPKM = 390009, + RPC_AUTH_GSS_SPKMI = 390010, + RPC_AUTH_GSS_SPKMP = 390011, }; enum rpc_msg_type { @@ -53,7 +64,10 @@ RPC_AUTH_REJECTEDCRED = 2, RPC_AUTH_BADVERF = 3, RPC_AUTH_REJECTEDVERF = 4, - RPC_AUTH_TOOWEAK = 5 + RPC_AUTH_TOOWEAK = 5, + /* RPCSEC_GSS errors */ + RPCSEC_GSS_CREDPROBLEM = 13, + RPCSEC_GSS_CTXPROBLEM = 14 }; #define RPC_PMAP_PROGRAM 100000 diff -u -r -N linux-2.5.49-02-auth2/include/linux/sunrpc/sched.h linux-2.5.49-03-rpc_gss/include/linux/sunrpc/sched.h --- linux-2.5.49-02-auth2/include/linux/sunrpc/sched.h 2002-11-18 13:34:36.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/include/linux/sunrpc/sched.h 2002-11-24 00:51:19.000000000 -0500 @@ -12,6 +12,7 @@ #include #include #include +#include /* * This is the actual RPC procedure call info. @@ -47,6 +48,8 @@ __u8 tk_garb_retry, tk_cred_retry, tk_suid_retry; + u32 tk_gss_seqno; /* rpcsec_gss sequence number + used on this request */ /* * timeout_fn to be executed by timer bottom half diff -u -r -N linux-2.5.49-02-auth2/include/linux/sunrpc/xdr.h linux-2.5.49-03-rpc_gss/include/linux/sunrpc/xdr.h --- linux-2.5.49-02-auth2/include/linux/sunrpc/xdr.h 2002-11-24 00:39:56.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/include/linux/sunrpc/xdr.h 2002-11-24 00:51:19.000000000 -0500 @@ -80,7 +80,9 @@ #define rpc_autherr_badverf __constant_htonl(RPC_AUTH_BADVERF) #define rpc_autherr_rejectedverf __constant_htonl(RPC_AUTH_REJECTEDVERF) #define rpc_autherr_tooweak __constant_htonl(RPC_AUTH_TOOWEAK) - +#define rpcsec_gsserr_credproblem __constant_htonl(RPCSEC_GSS_CREDPROBLEM) +#define rpcsec_gsserr_ctxproblem __constant_htonl(RPCSEC_GSS_CTXPROBLEM) +#define rpc_autherr_oldseqnum __constant_htonl(101) /* * Miscellaneous XDR helper functions diff -u -r -N linux-2.5.49-02-auth2/net/sunrpc/auth.c linux-2.5.49-03-rpc_gss/net/sunrpc/auth.c --- linux-2.5.49-02-auth2/net/sunrpc/auth.c 2002-11-24 00:51:16.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/net/sunrpc/auth.c 2002-11-24 00:51:19.000000000 -0500 @@ -24,6 +24,13 @@ NULL, /* others can be loadable modules */ }; +u32 +pseudoflavor_to_flavor(u32 flavor) { + if (flavor >= RPC_AUTH_MAXFLAVOR) + return RPC_AUTH_GSS; + return flavor; +} + int rpcauth_register(struct rpc_authops *ops) { @@ -51,13 +58,14 @@ } struct rpc_auth * -rpcauth_create(rpc_authflavor_t flavor, struct rpc_clnt *clnt) +rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) { struct rpc_authops *ops; + u32 flavor = pseudoflavor_to_flavor(pseudoflavor); if (flavor >= RPC_AUTH_MAXFLAVOR || !(ops = auth_flavors[flavor])) return NULL; - clnt->cl_auth = ops->create(clnt); + clnt->cl_auth = ops->create(clnt, pseudoflavor); return clnt->cl_auth; } @@ -218,7 +226,7 @@ rpcauth_destroy_credlist(&free); if (!cred) { - new = auth->au_ops->crcreate(acred, taskflags); + new = auth->au_ops->crcreate(auth, acred, taskflags); if (new) { #ifdef RPC_DEBUG new->cr_magic = RPCAUTH_CRED_MAGIC; diff -u -r -N linux-2.5.49-02-auth2/net/sunrpc/auth_gss/Makefile linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/Makefile --- linux-2.5.49-02-auth2/net/sunrpc/auth_gss/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/Makefile 2002-11-24 00:51:20.000000000 -0500 @@ -0,0 +1,12 @@ +# +# Makefile for Linux kernel rpcsec_gss implementation +# + +obj-$(CONFIG_SUNRPC_GSS) += auth_rpcgss.o + +export-objs := sunrpcgss_syms.o + +auth_rpcgss-objs := auth_gss.o gss_pseudoflavors.o gss_generic_token.o \ + sunrpcgss_syms.o gss_mech_switch.o + +include $(TOPDIR)/Rules.make diff -u -r -N linux-2.5.49-02-auth2/net/sunrpc/auth_gss/auth_gss.c linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/auth_gss.c --- linux-2.5.49-02-auth2/net/sunrpc/auth_gss/auth_gss.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/auth_gss.c 2002-11-24 00:51:20.000000000 -0500 @@ -0,0 +1,374 @@ +/* + * linux/net/sunrpc/auth_gss.c + * + * RPCSEC_GSS client authentication. + * + * Copyright (c) 2000 The Regents of the University of Michigan. + * All rights reserved. + * + * Dug Song + * Andy Adamson + * + * Redistribution and use in source and binary forms, with or without + * 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 + * notice, this list of conditions and the following disclaimer in the + * 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. + * + * $Id$ + */ + + +#define __NO_VERSION__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct rpc_authops authgss_ops; + +static struct rpc_credops gss_credops; + +#ifdef RPC_DEBUG +# define RPCDBG_FACILITY RPCDBG_AUTH +#endif + +#define NFS_NGROUPS 16 + +#define GSS_CRED_EXPIRE (60 * HZ) /* XXX: reasonable? */ +#define GSS_CRED_SLACK 1024 /* XXX: unused */ +#define GSS_VERF_SLACK 48 /* length of a krb5 verifier.*/ + +/* XXX this define must match the gssd define +* as it is passed to gssd to signal the use of +* machine creds should be part of the shared rpc interface */ + +#define CA_RUN_AS_MACHINE 0x00000200 + +/* dump the buffer in `emacs-hexl' style */ +#define isprint(c) ((c > 0x1f) && (c < 0x7f)) + +void +print_hexl(u32 *p, u_int length, u_int offset) +{ + u_int i, j, jm; + u8 c, *cp; + + dprintk("RPC: print_hexl: length %d\n",length); + dprintk("\n"); + cp = (u8 *) p; + + for (i = 0; i < length; i += 0x10) { + dprintk(" %04x: ", (u_int)(i + offset)); + jm = length - i; + jm = jm > 16 ? 16 : jm; + + for (j = 0; j < jm; j++) { + if ((j % 2) == 1) + dprintk("%02x ", (u_int)cp[i+j]); + else + dprintk("%02x", (u_int)cp[i+j]); + } + for (; j < 16; j++) { + if ((j % 2) == 1) + dprintk(" "); + else + dprintk(" "); + } + dprintk(" "); + + for (j = 0; j < jm; j++) { + c = cp[i+j]; + c = isprint(c) ? c : '.'; + dprintk("%c", c); + } + dprintk("\n"); + } +} + + +/* + * NOTE: we have the opportunity to use different + * parameters based on the input flavor (which must be a pseudoflavor) + */ +static struct rpc_auth * +gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) +{ + struct rpc_auth * auth; + + dprintk("RPC: creating GSS authenticator for client %p\n",clnt); + MOD_INC_USE_COUNT; + if (!(auth = kmalloc(sizeof(*auth), GFP_KERNEL))) + return NULL; + auth->au_cslack = GSS_CRED_SLACK >> 2; + auth->au_rslack = GSS_VERF_SLACK >> 2; + auth->au_expire = GSS_CRED_EXPIRE; + auth->au_ops = &authgss_ops; + auth->au_flavor = flavor; + + rpcauth_init_credcache(auth); + + return auth; +} + +static void +gss_destroy(struct rpc_auth *auth) +{ + dprintk("RPC: destroying GSS authenticator %p flavor %d\n", + auth, auth->au_flavor); + + rpcauth_free_credcache(auth); + + kfree(auth); + MOD_DEC_USE_COUNT; +} + +/* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure + * to create a new cred or context, so they check that things have been + * allocated before freeing them. */ +void +gss_destroy_ctx(struct gss_cl_ctx *ctx) +{ + + dprintk("RPC: gss_destroy_ctx\n"); + + if (ctx->gc_gss_ctx) + gss_delete_sec_context(&ctx->gc_gss_ctx); + + if (ctx->gc_wire_ctx.len > 0) { + kfree(ctx->gc_wire_ctx.data); + ctx->gc_wire_ctx.len = 0; + } + + kfree(ctx); + +} + +static void +gss_destroy_cred(struct rpc_cred *rc) +{ + struct gss_cred *cred = (struct gss_cred *)rc; + + dprintk("RPC: gss_destroy_cred \n"); + + if (cred->gc_ctx) + gss_destroy_ctx(cred->gc_ctx); + kfree(cred); +} + +static struct rpc_cred * +gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) +{ + struct gss_cred *cred = NULL; + + dprintk("RPC: gss_create_cred for uid %d, flavor %d\n", + acred->uid, auth->au_flavor); + + if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL))) + goto out_err; + + memset(cred, 0, sizeof(*cred)); + atomic_set(&cred->gc_count, 0); + cred->gc_uid = acred->uid; + /* + * Note: in order to force a call to call_refresh(), we deliberately + * fail to flag the credential as RPCAUTH_CRED_UPTODATE. + */ + cred->gc_flags = 0; + cred->gc_base.cr_ops = &gss_credops; + cred->gc_flavor = auth->au_flavor; + + return (struct rpc_cred *) cred; + +out_err: + dprintk("RPC: gss_create_cred failed\n"); + if (cred) gss_destroy_cred((struct rpc_cred *)cred); + return NULL; +} + +static int +gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags) +{ + return (rc->cr_uid == acred->uid); +} + +/* +* Marshal credentials. +* Maybe we should keep a cached credential for performance reasons. +*/ +static u32 * +gss_marshal(struct rpc_task *task, u32 *p, int ruid) +{ + struct gss_cred *cred = (struct gss_cred *) task->tk_msg.rpc_cred; + struct gss_cl_ctx *ctx = cred->gc_ctx; + u32 *cred_len; + struct rpc_rqst *req = task->tk_rqstp; + struct rpc_clnt *clnt = task->tk_client; + struct rpc_xprt *xprt = clnt->cl_xprt; + u32 *verfbase = req->rq_svec[0].iov_base; + u32 maj_stat = 0; + struct xdr_netobj bufin,bufout; + u32 service; + + dprintk("RPC: gss_marshal\n"); + + /* We compute the checksum for the verifier over the xdr-encoded bytes + * starting with the xid (which verfbase points to) and ending at + * the end of the credential. */ + if (xprt->stream) + verfbase++; /* See clnt.c:call_header() */ + + *p++ = htonl(RPC_AUTH_GSS); + cred_len = p++; + + service = gss_pseudoflavor_to_service(cred->gc_flavor); + if (service == 0) { + dprintk("Bad pseudoflavor %d in gss_marshal\n", + cred->gc_flavor); + return NULL; + } + spin_lock(&ctx->gc_seq_lock); + task->tk_gss_seqno = ctx->gc_seq++; + spin_unlock(&ctx->gc_seq_lock); + + *p++ = htonl((u32) RPC_GSS_VERSION); + *p++ = htonl((u32) ctx->gc_proc); + *p++ = htonl((u32) task->tk_gss_seqno); + *p++ = htonl((u32) service); + p = xdr_encode_netobj(p, &ctx->gc_wire_ctx); + *cred_len = htonl((p - (cred_len + 1)) << 2); + + /* Marshal verifier. */ + bufin.data = (u8 *)verfbase; + bufin.len = (p - verfbase) << 2; + + /* set verifier flavor*/ + *p++ = htonl(RPC_AUTH_GSS); + + maj_stat = gss_get_mic(ctx->gc_gss_ctx, + GSS_C_QOP_DEFAULT, + &bufin, &bufout); + if(maj_stat != 0){ + printk("gss_marshal: gss_get_mic FAILED (%d)\n", + maj_stat); + return(NULL); + } + p = xdr_encode_netobj(p, &bufout); + return p; +} + +/* +* Refresh credentials. XXX - finish +*/ +static int +gss_refresh(struct rpc_task *task) +{ + /* Insert upcall here ! */ + task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE; + return task->tk_status = -EACCES; +} + +static u32 * +gss_validate(struct rpc_task *task, u32 *p) +{ + struct gss_cred *cred = (struct gss_cred *)task->tk_msg.rpc_cred; + struct gss_cl_ctx *ctx = cred->gc_ctx; + u32 seq, qop_state; + struct xdr_netobj bufin; + struct xdr_netobj bufout; + u32 flav,len; + int code = 0; + + dprintk("RPC: gss_validate\n"); + + flav = ntohl(*p++); + if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE) { + printk("RPC: giant verf size: %ld\n", (unsigned long) len); + return NULL; + } + dprintk("RPC: gss_validate: verifier flavor %d, len %d\n", flav, len); + + if (flav != RPC_AUTH_GSS) { + printk("RPC: bad verf flavor: %ld\n", (unsigned long)flav); + return NULL; + } + seq = htonl(task->tk_gss_seqno); + bufin.data = (u8 *) &seq; + bufin.len = sizeof(seq); + bufout.data = (u8 *) p; + bufout.len = len; + + if ((code = gss_verify_mic(ctx->gc_gss_ctx, + &bufin, &bufout, &qop_state) < 0)) + return NULL; + task->tk_auth->au_rslack = XDR_QUADLEN(len) + 2; + dprintk("RPC: GSS gss_validate: gss_verify_mic succeeded.\n"); + return p + XDR_QUADLEN(len); +} + +static struct rpc_authops authgss_ops = { + .au_flavor = RPC_AUTH_GSS, +#ifdef RPC_DEBUG + .au_name = "RPCSEC_GSS", +#endif + .create = gss_create, + .destroy = gss_destroy, + .crcreate = gss_create_cred +}; + +static struct rpc_credops gss_credops = { + .crdestroy = gss_destroy_cred, + .crmatch = gss_match, + .crmarshal = gss_marshal, + .crrefresh = gss_refresh, + .crvalidate = gss_validate, +}; + +extern void gss_svc_ctx_init(void); + +/* + * Initialize RPCSEC_GSS module + */ +static int __init init_rpcsec_gss(void) +{ + int err = 0; + + err = rpcauth_register(&authgss_ops); + return err; +} + +static void __exit exit_rpcsec_gss(void) +{ + gss_mech_unregister_all(); + rpcauth_unregister(&authgss_ops); +} + +MODULE_LICENSE("GPL"); +module_init(init_rpcsec_gss) +module_exit(exit_rpcsec_gss) diff -u -r -N linux-2.5.49-02-auth2/net/sunrpc/auth_gss/gss_generic_token.c linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/gss_generic_token.c --- linux-2.5.49-02-auth2/net/sunrpc/auth_gss/gss_generic_token.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/gss_generic_token.c 2002-11-24 00:51:20.000000000 -0500 @@ -0,0 +1,269 @@ +/* + * linux/net/sunrpc/gss_generic_token.c + * + * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/generic/util_token.c + * + * Copyright (c) 2000 The Regents of the University of Michigan. + * All rights reserved. + * + * Andy Adamson + */ + +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + + +#ifdef RPC_DEBUG +# define RPCDBG_FACILITY RPCDBG_AUTH +#endif + + +/* TWRITE_STR from gssapiP_generic.h */ +#define TWRITE_STR(ptr, str, len) \ + memcpy((ptr), (char *) (str), (len)); \ + (ptr) += (len); + +/* XXXX this code currently makes the assumption that a mech oid will + never be longer than 127 bytes. This assumption is not inherent in + the interfaces, so the code can be fixed if the OSI namespace + balloons unexpectedly. */ + +/* Each token looks like this: + +0x60 tag for APPLICATION 0, SEQUENCE + (constructed, definite-length) + possible multiple bytes, need to parse/generate + 0x06 tag for OBJECT IDENTIFIER + compile-time constant string (assume 1 byte) + compile-time constant string + the ANY containing the application token + bytes 0,1 are the token type + bytes 2,n are the token data + +For the purposes of this abstraction, the token "header" consists of +the sequence tag and length octets, the mech OID DER encoding, and the +first two inner bytes, which indicate the token type. The token +"body" consists of everything else. + +*/ + +static int +der_length_size( int length) +{ + if (length < (1<<7)) + return(1); + else if (length < (1<<8)) + return(2); +#if (SIZEOF_INT == 2) + else + return(3); +#else + else if (length < (1<<16)) + return(3); + else if (length < (1<<24)) + return(4); + else + return(5); +#endif +} + +static void +der_write_length(unsigned char **buf, int length) +{ + if (length < (1<<7)) { + *(*buf)++ = (unsigned char) length; + } else { + *(*buf)++ = (unsigned char) (der_length_size(length)+127); +#if (SIZEOF_INT > 2) + if (length >= (1<<24)) + *(*buf)++ = (unsigned char) (length>>24); + if (length >= (1<<16)) + *(*buf)++ = (unsigned char) ((length>>16)&0xff); +#endif + if (length >= (1<<8)) + *(*buf)++ = (unsigned char) ((length>>8)&0xff); + *(*buf)++ = (unsigned char) (length&0xff); + } +} + +/* returns decoded length, or < 0 on failure. Advances buf and + decrements bufsize */ + +static int +der_read_length(unsigned char **buf, int *bufsize) +{ + unsigned char sf; + int ret; + + if (*bufsize < 1) + return(-1); + sf = *(*buf)++; + (*bufsize)--; + if (sf & 0x80) { + if ((sf &= 0x7f) > ((*bufsize)-1)) + return(-1); + if (sf > SIZEOF_INT) + return (-1); + ret = 0; + for (; sf; sf--) { + ret = (ret<<8) + (*(*buf)++); + (*bufsize)--; + } + } else { + ret = sf; + } + + return(ret); +} + +/* returns the length of a token, given the mech oid and the body size */ + +int +g_token_size(struct xdr_netobj *mech, unsigned int body_size) +{ + /* set body_size to sequence contents size */ + body_size += 4 + (int) mech->len; /* NEED overflow check */ + return(1 + der_length_size(body_size) + body_size); +} + +/* fills in a buffer with the token header. The buffer is assumed to + be the right size. buf is advanced past the token header */ + +void +g_make_token_header(struct xdr_netobj *mech, int body_size, unsigned char **buf, + int tok_type) +{ + *(*buf)++ = 0x60; + der_write_length(buf, 4 + mech->len + body_size); + *(*buf)++ = 0x06; + *(*buf)++ = (unsigned char) mech->len; + TWRITE_STR(*buf, mech->data, ((int) mech->len)); + *(*buf)++ = (unsigned char) ((tok_type>>8)&0xff); + *(*buf)++ = (unsigned char) (tok_type&0xff); +} + +/* + * Given a buffer containing a token, reads and verifies the token, + * leaving buf advanced past the token header, and setting body_size + * to the number of remaining bytes. Returns 0 on success, + * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the + * mechanism in the token does not match the mech argument. buf and + * *body_size are left unmodified on error. + */ +u32 +g_verify_token_header(struct xdr_netobj *mech, int *body_size, + unsigned char **buf_in, int tok_type, int toksize) +{ + unsigned char *buf = *buf_in; + int seqsize; + struct xdr_netobj toid; + int ret = 0; + + if ((toksize-=1) < 0) + return(G_BAD_TOK_HEADER); + if (*buf++ != 0x60) + return(G_BAD_TOK_HEADER); + + if ((seqsize = der_read_length(&buf, &toksize)) < 0) + return(G_BAD_TOK_HEADER); + + if (seqsize != toksize) + return(G_BAD_TOK_HEADER); + + if ((toksize-=1) < 0) + return(G_BAD_TOK_HEADER); + if (*buf++ != 0x06) + return(G_BAD_TOK_HEADER); + + if ((toksize-=1) < 0) + return(G_BAD_TOK_HEADER); + toid.len = *buf++; + + if ((toksize-=toid.len) < 0) + return(G_BAD_TOK_HEADER); + toid.data = buf; + buf+=toid.len; + + if (! g_OID_equal(&toid, mech)) + ret = G_WRONG_MECH; + + /* G_WRONG_MECH is not returned immediately because it's more important + to return G_BAD_TOK_HEADER if the token header is in fact bad */ + + if ((toksize-=2) < 0) + return(G_BAD_TOK_HEADER); + + if (ret) + return(ret); + + if ((*buf++ != ((tok_type>>8)&0xff)) || (*buf++ != (tok_type&0xff))) + return(G_WRONG_TOKID); + + if (!ret) { + *buf_in = buf; + *body_size = toksize; + } + + return(ret); +} + +/* Given a buffer containing a token, returns a copy of the mech oid in + * the parameter mech. */ +u32 +g_get_mech_oid(struct xdr_netobj *mech, struct xdr_netobj * in_buf) +{ + unsigned char *buf = in_buf->data; + int len = in_buf->len; + int ret=0; + int seqsize; + + if ((len-=1) < 0) + return(G_BAD_TOK_HEADER); + if (*buf++ != 0x60) + return(G_BAD_TOK_HEADER); + + if ((seqsize = der_read_length(&buf, &len)) < 0) + return(G_BAD_TOK_HEADER); + + if ((len-=1) < 0) + return(G_BAD_TOK_HEADER); + if (*buf++ != 0x06) + return(G_BAD_TOK_HEADER); + + if ((len-=1) < 0) + return(G_BAD_TOK_HEADER); + mech->len = *buf++; + + if ((len-=mech->len) < 0) + return(G_BAD_TOK_HEADER); + if (!(mech->data = kmalloc(mech->len, GFP_KERNEL))) + return(G_BUFFER_ALLOC); + memcpy(mech->data, buf, mech->len); + + return ret; +} diff -u -r -N linux-2.5.49-02-auth2/net/sunrpc/auth_gss/gss_mech_switch.c linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/gss_mech_switch.c --- linux-2.5.49-02-auth2/net/sunrpc/auth_gss/gss_mech_switch.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/gss_mech_switch.c 2002-11-24 00:51:20.000000000 -0500 @@ -0,0 +1,283 @@ +/* + * linux/net/sunrpc/gss_mech_switch.c + * + * Copyright (c) 2001 The Regents of the University of Michigan. + * All rights reserved. + * + * J. Bruce Fields + * + * Redistribution and use in source and binary forms, with or without + * 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 + * notice, this list of conditions and the following disclaimer in the + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RPC_DEBUG +# define RPCDBG_FACILITY RPCDBG_AUTH +#endif + +static LIST_HEAD(registered_mechs); +static spinlock_t registered_mechs_lock = SPIN_LOCK_UNLOCKED; + +/* Reference counting: The reference count includes the reference in the + * global registered_mechs list. That reference will never diseappear + * (so the reference count will never go below 1) until after the mech + * is removed from the list. Nothing can be removed from the list without + * first getting the registered_mechs_lock, so a gss_api_mech won't diseappear + * from underneath us while we hold the registered_mech_lock. */ + +int +gss_mech_register(struct xdr_netobj * mech_type, struct gss_api_ops * ops) +{ + struct gss_api_mech *gm; + + if (!(gm = kmalloc(sizeof(*gm), GFP_KERNEL))) { + printk("Failed to allocate memory in gss_mech_register"); + return -1; + } + gm->gm_oid.len = mech_type->len; + if (!(gm->gm_oid.data = kmalloc(mech_type->len, GFP_KERNEL))) { + printk("Failed to allocate memory in gss_mech_register"); + return -1; + } + memcpy(gm->gm_oid.data, mech_type->data, mech_type->len); + /* We're counting the reference in the registered_mechs list: */ + atomic_set(&gm->gm_count, 1); + gm->gm_ops = ops; + + spin_lock(®istered_mechs_lock); + list_add(&gm->gm_list, ®istered_mechs); + spin_unlock(®istered_mechs_lock); + dprintk("RPC: gss_mech_register: registered mechanism with oid:\n"); + print_hexl((u32 *)mech_type->data, mech_type->len, 0); + return 0; +} + +/* The following must be called with spinlock held: */ +int +do_gss_mech_unregister(struct gss_api_mech *gm) +{ + + list_del(&gm->gm_list); + + dprintk("RPC: unregistered mechanism with oid:\n"); + print_hexl((u32 *)gm->gm_oid.data, gm->gm_oid.len, 0); + if (!gss_mech_put(gm)) { + dprintk("RPC: We just unregistered a gss_mechanism which" + " someone is still using.\n"); + return -1; + } else { + return 0; + } +} + +int +gss_mech_unregister(struct gss_api_mech *gm) +{ + int status; + + spin_lock(®istered_mechs_lock); + status = do_gss_mech_unregister(gm); + spin_unlock(®istered_mechs_lock); + return status; +} + +int +gss_mech_unregister_all(void) +{ + struct list_head *pos; + struct gss_api_mech *gm; + int status = 0; + + spin_lock(®istered_mechs_lock); + while (!list_empty(®istered_mechs)) { + pos = registered_mechs.next; + gm = list_entry(pos, struct gss_api_mech, gm_list); + if (do_gss_mech_unregister(gm)) + status = -1; + } + spin_unlock(®istered_mechs_lock); + return status; +} + +struct gss_api_mech * +gss_mech_get(struct gss_api_mech *gm) +{ + atomic_inc(&gm->gm_count); + return gm; +} + +struct gss_api_mech * +gss_mech_get_by_OID(struct xdr_netobj *mech_type) +{ + struct gss_api_mech *pos, *gm = NULL; + + dprintk("RPC: gss_mech_get_by_OID searching for mechanism with OID:\n"); + print_hexl((u32 *)mech_type->data, mech_type->len, 0); + spin_lock(®istered_mechs_lock); + list_for_each_entry(pos, ®istered_mechs, gm_list) { + if ((pos->gm_oid.len == mech_type->len) + && !memcmp(pos->gm_oid.data, mech_type->data, + mech_type->len)) { + gm = gss_mech_get(pos); + break; + } + } + spin_unlock(®istered_mechs_lock); + dprintk("RPC: gss_mech_get_by_OID %s it\n", gm ? "found" : "didn't find"); + return gm; +} + +int +gss_mech_put(struct gss_api_mech * gm) +{ + if (atomic_dec_and_test(&gm->gm_count)) { + if (gm->gm_oid.len >0) + kfree(gm->gm_oid.data); + kfree(gm); + return 1; + } else { + return 0; + } +} + +/* In all functions that take a context handle, the caller is responsible for + * verifying that context handle (i.e., for making sure the given pointer, if + * it was taken directly off the wire, actually points to a real context). */ + +/* Used on the server side to accept a token created by the client's + * gss_init_sec_context, create a ctx_id to be used on the server side, and + * construct a token to be returned to the client. Note that this prototype + * is much simplified compared to the one specified in the gss-api RFCs; if + * it turns out we need some of the other parameters we may end up reinstating + * them later. */ +u32 +gss_accept_sec_context(struct gss_ctx **ctx_id, + struct xdr_netobj *input_token, + uid_t *initiator_uid, + struct xdr_netobj *output_token, + u32 *ret_flags) +{ + struct xdr_netobj mech; + u32 maj_stat; + struct xdr_netobj client_name; + + if (!*ctx_id) { + if (!(*ctx_id = kmalloc(sizeof(**ctx_id), GFP_KERNEL))) + return GSS_S_FAILURE; + memset(*ctx_id, 0, sizeof(**ctx_id)); + if (g_get_mech_oid(&mech, input_token)) + return GSS_S_DEFECTIVE_TOKEN; + if (!((*ctx_id)->mech_type = gss_mech_get_by_OID(&mech))) + return GSS_S_BAD_MECH; + } + maj_stat = (*ctx_id)->mech_type->gm_ops + ->gss_accept_sec_context(*ctx_id, input_token, + &client_name, output_token, ret_flags); + /* XXX u32/uid_t conversion? (Also--shouldn't this be mech-specific?)*/ + if (name_get_uid(client_name.data, client_name.len, initiator_uid) < 0) + return GSS_S_DEFECTIVE_CREDENTIAL; + kfree(client_name.data); + return maj_stat; +} + +/* The mech could probably be determined from the token instead, but it's just + * as easy for now to pass it in. */ +u32 +gss_import_sec_context(struct xdr_netobj *input_token, + struct gss_api_mech *mech, + struct gss_ctx **ctx_id) +{ + if (!(*ctx_id = kmalloc(sizeof(**ctx_id), GFP_KERNEL))) + return GSS_S_FAILURE; + memset(*ctx_id, 0, sizeof(**ctx_id)); + (*ctx_id)->mech_type = gss_mech_get(mech); + + return mech->gm_ops + ->gss_import_sec_context(input_token, *ctx_id); +} + +/* gss_verify_mic: hash messages_buffer and return gss verify token. */ + +u32 +gss_get_mic(struct gss_ctx *context_handle, + u32 qop, + struct xdr_netobj *message_buffer, + struct xdr_netobj *message_token) +{ + return context_handle->mech_type->gm_ops + ->gss_get_mic(context_handle, + qop, + message_buffer, + message_token); +} + +/* gss_verify_mic: hash messages_buffer and return gss verify token. */ + +u32 +gss_verify_mic(struct gss_ctx *context_handle, + struct xdr_netobj *signbuf, + struct xdr_netobj *checksum, + u32 *qstate) +{ + return context_handle->mech_type->gm_ops + ->gss_verify_mic(context_handle, + signbuf, + checksum, + qstate); +} + +/* 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) +{ + dprintk("gss_delete_sec_context deleting %p\n",*context_handle); + + if (!*context_handle) + return(GSS_S_NO_CONTEXT); + if ((*context_handle)->internal_ctx_id != 0) + (*context_handle)->mech_type->gm_ops + ->gss_delete_sec_context((*context_handle) + ->internal_ctx_id); + if ((*context_handle)->mech_type) + gss_mech_put((*context_handle)->mech_type); + kfree(*context_handle); + *context_handle=NULL; + return GSS_S_COMPLETE; +} diff -u -r -N linux-2.5.49-02-auth2/net/sunrpc/auth_gss/gss_pseudoflavors.c linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/gss_pseudoflavors.c --- linux-2.5.49-02-auth2/net/sunrpc/auth_gss/gss_pseudoflavors.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/gss_pseudoflavors.c 2002-11-24 00:51:20.000000000 -0500 @@ -0,0 +1,235 @@ +/* + * linux/net/sunrpc/gss_union.c + * + * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/generic code + * + * Copyright (c) 2001 The Regents of the University of Michigan. + * All rights reserved. + * + * Andy Adamson + * + */ + +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#ifdef RPC_DEBUG +# define RPCDBG_FACILITY RPCDBG_AUTH +#endif + +static LIST_HEAD(registered_triples); +static spinlock_t registered_triples_lock = SPIN_LOCK_UNLOCKED; + +/* The following must be called with spinlock held: */ +static struct sup_sec_triple * +do_lookup_triple_by_pseudoflavor(u32 pseudoflavor) +{ + struct sup_sec_triple *pos, *triple = NULL; + + list_for_each_entry(pos, ®istered_triples, triples) { + if (pos->pseudoflavor == pseudoflavor) { + triple = pos; + break; + } + } + return triple; +} + +/* XXX Need to think about reference counting of triples and of mechs. + * Currently we do no reference counting of triples, and I think that's + * probably OK given the reference counting on mechs, but there's probably + * a better way to do all this. */ + +int +gss_register_triple(u32 pseudoflavor, struct gss_api_mech *mech, + u32 qop, u32 service) +{ + struct sup_sec_triple *triple; + + if (!(triple = kmalloc(sizeof(*triple), GFP_KERNEL))) { + printk("Alloc failed in gss_register_triple"); + goto err; + } + triple->pseudoflavor = pseudoflavor; + triple->mech = gss_mech_get_by_OID(&mech->gm_oid); + triple->qop = qop; + triple->service = service; + + spin_lock(®istered_triples_lock); + if (do_lookup_triple_by_pseudoflavor(pseudoflavor)) { + printk("Registered pseudoflavor %d again\n", pseudoflavor); + goto err_unlock; + } + list_add(&triple->triples, ®istered_triples); + spin_unlock(®istered_triples_lock); + dprintk("RPC: registered pseudoflavor %d\n", pseudoflavor); + + return 0; + +err_unlock: + spin_unlock(®istered_triples_lock); +err: + return -1; +} + +int +gss_unregister_triple(u32 pseudoflavor) +{ + struct sup_sec_triple *triple; + + spin_lock(®istered_triples_lock); + if (!(triple = do_lookup_triple_by_pseudoflavor(pseudoflavor))) { + spin_unlock(®istered_triples_lock); + printk("Can't unregister unregistered pseudoflavor %d\n", + pseudoflavor); + return -1; + } + list_del(&triple->triples); + spin_unlock(®istered_triples_lock); + gss_mech_put(triple->mech); + kfree(triple); + return 0; + +} + +void +print_sec_triple(struct xdr_netobj *oid,u32 qop,u32 service) +{ + dprintk("RPC: print_sec_triple:\n"); + dprintk(" oid_len %d\n oid :\n",oid->len); + print_hexl((u32 *)oid->data,oid->len,0); + dprintk(" qop %d\n",qop); + dprintk(" service %d\n",service); +} + +/* Function: gss_get_cmp_triples + * + * Description: search sec_triples for a matching security triple + * return pseudoflavor if match, else 0 + * (Note that 0 is a valid pseudoflavor, but not for any gss pseudoflavor + * (0 means auth_null), so this shouldn't cause confusion.) + */ +u32 +gss_cmp_triples(u32 oid_len, char *oid_data, u32 qop, u32 service) +{ + struct sup_sec_triple *triple; + u32 pseudoflavor = 0; + struct xdr_netobj oid; + + oid.len = oid_len; + oid.data = oid_data; + + dprintk("RPC: gss_cmp_triples \n"); + print_sec_triple(&oid,qop,service); + + spin_lock(®istered_triples_lock); + list_for_each_entry(triple, ®istered_triples, triples) { + if((g_OID_equal(&oid, &triple->mech->gm_oid)) + && (qop == triple->qop) + && (service == triple->service)) { + pseudoflavor = triple->pseudoflavor; + break; + } + } + spin_unlock(®istered_triples_lock); + dprintk("RPC: gss_cmp_triples return %d\n", pseudoflavor); + return pseudoflavor; +} + +u32 +gss_get_pseudoflavor(struct gss_ctx *ctx, u32 qop, u32 service) +{ + return gss_cmp_triples(ctx->mech_type->gm_oid.len, + ctx->mech_type->gm_oid.data, + qop, service); +} + +/* Returns nonzero iff the given pseudoflavor is in the supported list. + * (Note that without incrementing a reference count or anything, this + * doesn't give any guarantees.) */ +int +gss_pseudoflavor_supported(u32 pseudoflavor) +{ + struct sup_sec_triple *triple; + + spin_lock(®istered_triples_lock); + triple = do_lookup_triple_by_pseudoflavor(pseudoflavor); + spin_unlock(®istered_triples_lock); + return (triple ? 1 : 0); +} + +u32 +gss_pseudoflavor_to_service(u32 pseudoflavor) +{ + struct sup_sec_triple *triple; + + spin_lock(®istered_triples_lock); + triple = do_lookup_triple_by_pseudoflavor(pseudoflavor); + spin_unlock(®istered_triples_lock); + if (!triple) { + dprintk("RPC: gss_pseudoflavor_to_service called with" + " unsupported pseudoflavor %d\n", pseudoflavor); + return 0; + } + return triple->service; +} + +struct gss_api_mech * +gss_pseudoflavor_to_mech(u32 pseudoflavor) { + struct sup_sec_triple *triple; + struct gss_api_mech *mech = NULL; + + spin_lock(®istered_triples_lock); + triple = do_lookup_triple_by_pseudoflavor(pseudoflavor); + spin_unlock(®istered_triples_lock); + if (triple) + mech = gss_mech_get(triple->mech); + else + dprintk("RPC: gss_pseudoflavor_to_mech called with" + " unsupported pseudoflavor %d\n", pseudoflavor); + return mech; +} + +int +gss_pseudoflavor_to_mechOID(u32 pseudoflavor, struct xdr_netobj * oid) +{ + struct gss_api_mech *mech; + + mech = gss_pseudoflavor_to_mech(pseudoflavor); + if (!mech) { + dprintk("RPC: gss_pseudoflavor_to_mechOID called with" + " unsupported pseudoflavor %d\n", pseudoflavor); + return -1; + } + oid->len = mech->gm_oid.len; + if (!(oid->data = kmalloc(oid->len, GFP_KERNEL))) + return -1; + memcpy(oid->data, mech->gm_oid.data, oid->len); + gss_mech_put(mech); + return 0; +} diff -u -r -N linux-2.5.49-02-auth2/net/sunrpc/auth_gss/sunrpcgss_syms.c linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/sunrpcgss_syms.c --- linux-2.5.49-02-auth2/net/sunrpc/auth_gss/sunrpcgss_syms.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/net/sunrpc/auth_gss/sunrpcgss_syms.c 2002-11-24 00:51:20.000000000 -0500 @@ -0,0 +1,34 @@ +#define __NO_VERSION__ +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +/* sec_triples: */ +EXPORT_SYMBOL(gss_register_triple); +EXPORT_SYMBOL(gss_unregister_triple); +EXPORT_SYMBOL(gss_cmp_triples); +EXPORT_SYMBOL(gss_pseudoflavor_to_mechOID); +EXPORT_SYMBOL(gss_pseudoflavor_supported); +EXPORT_SYMBOL(gss_pseudoflavor_to_service); + +/* registering gss mechanisms to the mech switching code: */ +EXPORT_SYMBOL(gss_mech_register); +EXPORT_SYMBOL(gss_mech_get); +EXPORT_SYMBOL(gss_mech_get_by_OID); +EXPORT_SYMBOL(gss_mech_put); + +/* generic functionality in gss code: */ +EXPORT_SYMBOL(g_make_token_header); +EXPORT_SYMBOL(g_verify_token_header); +EXPORT_SYMBOL(g_token_size); + +/* debug */ +EXPORT_SYMBOL(print_hexl); diff -u -r -N linux-2.5.49-02-auth2/net/sunrpc/auth_null.c linux-2.5.49-03-rpc_gss/net/sunrpc/auth_null.c --- linux-2.5.49-02-auth2/net/sunrpc/auth_null.c 2002-11-24 00:51:16.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/net/sunrpc/auth_null.c 2002-11-24 00:51:20.000000000 -0500 @@ -20,7 +20,7 @@ static struct rpc_credops null_credops; static struct rpc_auth * -nul_create(struct rpc_clnt *clnt) +nul_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) { struct rpc_auth *auth; @@ -48,7 +48,7 @@ * Create NULL creds for current process */ static struct rpc_cred * -nul_create_cred(struct auth_cred *acred, int flags) +nul_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) { struct rpc_cred *cred; diff -u -r -N linux-2.5.49-02-auth2/net/sunrpc/auth_unix.c linux-2.5.49-03-rpc_gss/net/sunrpc/auth_unix.c --- linux-2.5.49-02-auth2/net/sunrpc/auth_unix.c 2002-11-24 00:51:16.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/net/sunrpc/auth_unix.c 2002-11-24 00:51:20.000000000 -0500 @@ -38,7 +38,7 @@ static struct rpc_credops unix_credops; static struct rpc_auth * -unx_create(struct rpc_clnt *clnt) +unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) { struct rpc_auth *auth; @@ -64,7 +64,7 @@ } static struct rpc_cred * -unx_create_cred(struct auth_cred *acred, int flags) +unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) { struct unx_cred *cred; int i; @@ -208,7 +208,7 @@ } size = ntohl(*p++); - if (size > 400) { + if (size > RPC_MAX_AUTH_SIZE) { printk("RPC: giant verf size: %u\n", size); return NULL; } diff -u -r -N linux-2.5.49-02-auth2/net/sunrpc/clnt.c linux-2.5.49-03-rpc_gss/net/sunrpc/clnt.c --- linux-2.5.49-02-auth2/net/sunrpc/clnt.c 2002-11-18 13:34:36.000000000 -0500 +++ linux-2.5.49-03-rpc_gss/net/sunrpc/clnt.c 2002-11-24 00:51:20.000000000 -0500 @@ -34,7 +34,7 @@ #include -#define RPC_SLACK_SPACE 512 /* total overkill */ +#define RPC_SLACK_SPACE (1024) /* total overkill */ #ifdef RPC_DEBUG # define RPCDBG_FACILITY RPCDBG_CALL @@ -533,7 +533,8 @@ if (!(p = call_header(task))) { printk(KERN_INFO "RPC: call_header failed, exit EIO\n"); rpc_exit(task, -EIO); - } else + return; + } if (encode && (status = encode(req, p, task->tk_msg.rpc_argp)) < 0) { printk(KERN_WARNING "%s: can't encode arguments: %d\n", clnt->cl_protname, -status);