From ea3d7030c0c6118b636ea8909a5583b94d819e3a Mon Sep 17 00:00:00 2001 From: dfr Date: Wed, 6 Aug 2008 14:02:05 +0000 Subject: Add an implementation of the RPCSEC_GSS authentication protocol for RPC. This is based on an old implementation from the University of Michigan with lots of changes and fixes by me and the addition of a Solaris-compatible API. Sponsored by: Isilon Systems Reviewed by: alfred --- include/gssapi/gssapi.h | 9 +++ include/rpc/Makefile | 2 +- include/rpc/auth.h | 18 ++++- include/rpc/rpcsec_gss.h | 179 +++++++++++++++++++++++++++++++++++++++++++++++ include/rpc/svc.h | 43 ++++++++++++ 5 files changed, 248 insertions(+), 3 deletions(-) create mode 100644 include/rpc/rpcsec_gss.h (limited to 'include') diff --git a/include/gssapi/gssapi.h b/include/gssapi/gssapi.h index 30f6876..16a588e 100644 --- a/include/gssapi/gssapi.h +++ b/include/gssapi/gssapi.h @@ -837,6 +837,15 @@ OM_uint32 gss_pseudo_random gss_buffer_t /* buffer for result */ ); +#ifdef _UID_T_DECLARED +OM_uint32 gss_pname_to_uid + (OM_uint32 *, /* minor status */ + const gss_name_t pname, /* principal name */ + const gss_OID mech, /* mechanism to query */ + uid_t *uidp /* pointer to UID for result */ + ); +#endif + __END_DECLS #endif /* _GSSAPI_GSSAPI_H_ */ diff --git a/include/rpc/Makefile b/include/rpc/Makefile index ee78fcf..40d4c47 100644 --- a/include/rpc/Makefile +++ b/include/rpc/Makefile @@ -11,7 +11,7 @@ XFILES= rpcb_prot.x HFILES= auth.h auth_unix.h clnt.h clnt_soc.h clnt_stat.h \ nettype.h pmap_clnt.h pmap_prot.h pmap_rmt.h raw.h \ - rpc.h rpc_msg.h rpcb_clnt.h rpcent.h rpc_com.h \ + rpc.h rpc_msg.h rpcb_clnt.h rpcent.h rpc_com.h rpcsec_gss.h \ svc.h svc_auth.h svc_soc.h svc_dg.h xdr.h # Secure RPC diff --git a/include/rpc/auth.h b/include/rpc/auth.h index fd48421..d39ad12 100644 --- a/include/rpc/auth.h +++ b/include/rpc/auth.h @@ -132,7 +132,7 @@ enum auth_stat { * failed locally */ AUTH_INVALIDRESP=6, /* bogus response verifier */ - AUTH_FAILED=7 /* some unknown reason */ + AUTH_FAILED=7, /* some unknown reason */ #ifdef KERBEROS /* * kerberos errors @@ -142,8 +142,14 @@ enum auth_stat { AUTH_TIMEEXPIRE = 9, /* time of credential expired */ AUTH_TKT_FILE = 10, /* something wrong with ticket file */ AUTH_DECODE = 11, /* can't decode authenticator */ - AUTH_NET_ADDR = 12 /* wrong net address in ticket */ + AUTH_NET_ADDR = 12, /* wrong net address in ticket */ #endif /* KERBEROS */ + /* + * RPCSEC_GSS errors + */ + RPCSEC_GSS_CREDPROBLEM = 13, + RPCSEC_GSS_CTXPROBLEM = 14, + RPCSEC_GSS_NODISPATCH = 0x8000000 }; union des_block { @@ -352,5 +358,13 @@ __END_DECLS #define AUTH_DH 3 /* for Diffie-Hellman mechanism */ #define AUTH_DES AUTH_DH /* for backward compatibility */ #define AUTH_KERB 4 /* kerberos style */ +#define RPCSEC_GSS 6 /* RPCSEC_GSS */ + +/* + * Pseudo auth flavors for RPCSEC_GSS. + */ +#define RPCSEC_GSS_KRB5 390003 +#define RPCSEC_GSS_KRB5I 390004 +#define RPCSEC_GSS_KRB5P 390005 #endif /* !_RPC_AUTH_H */ diff --git a/include/rpc/rpcsec_gss.h b/include/rpc/rpcsec_gss.h new file mode 100644 index 0000000..ccd346f --- /dev/null +++ b/include/rpc/rpcsec_gss.h @@ -0,0 +1,179 @@ +/*- + * Copyright (c) 2008 Doug Rabson + * All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _RPCSEC_GSS_H +#define _RPCSEC_GSS_H + +#include + +#ifndef MAX_GSS_MECH +#define MAX_GSS_MECH 64 +#endif + +/* + * Define the types of security service required for rpc_gss_seccreate(). + */ +typedef enum { + rpc_gss_svc_default = 0, + rpc_gss_svc_none = 1, + rpc_gss_svc_integrity = 2, + rpc_gss_svc_privacy = 3 +} rpc_gss_service_t; + +/* + * Structure containing options for rpc_gss_seccreate(). + */ +typedef struct { + int req_flags; /* GSS request bits */ + int time_req; /* requested credential lifetime */ + gss_cred_id_t my_cred; /* GSS credential */ + gss_channel_bindings_t input_channel_bindings; +} rpc_gss_options_req_t; + +/* + * Structure containing options returned by rpc_gss_seccreate(). + */ +typedef struct { + int major_status; + int minor_status; + u_int rpcsec_version; + int ret_flags; + int time_req; + gss_ctx_id_t gss_context; + char actual_mechanism[MAX_GSS_MECH]; +} rpc_gss_options_ret_t; + +/* + * Client principal type. Used as an argument to + * rpc_gss_get_principal_name(). Also referenced by the + * rpc_gss_rawcred_t structure. + */ +typedef struct { + int len; + char name[1]; +} *rpc_gss_principal_t; + +/* + * Structure for raw credentials used by rpc_gss_getcred() and + * rpc_gss_set_callback(). + */ +typedef struct { + u_int version; /* RPC version number */ + const char *mechanism; /* security mechanism */ + const char *qop; /* quality of protection */ + rpc_gss_principal_t client_principal; /* client name */ + const char *svc_principal; /* server name */ + rpc_gss_service_t service; /* service type */ +} rpc_gss_rawcred_t; + +/* + * Unix credentials derived from raw credentials. Returned by + * rpc_gss_getcred(). + */ +typedef struct { + uid_t uid; /* user ID */ + gid_t gid; /* group ID */ + short gidlen; + gid_t *gidlist; /* list of groups */ +} rpc_gss_ucred_t; + +/* + * Structure used to enforce a particular QOP and service. + */ +typedef struct { + bool_t locked; + rpc_gss_rawcred_t *raw_cred; +} rpc_gss_lock_t; + +/* + * Callback structure used by rpc_gss_set_callback(). + */ +typedef struct { + u_int program; /* RPC program number */ + u_int version; /* RPC version number */ + /* user defined callback */ + bool_t (*callback)(struct svc_req *req, + gss_cred_id_t deleg, + gss_ctx_id_t gss_context, + rpc_gss_lock_t *lock, + void **cookie); +} rpc_gss_callback_t; + +/* + * Structure used to return error information by rpc_gss_get_error() + */ +typedef struct { + int rpc_gss_error; + int system_error; /* same as errno */ +} rpc_gss_error_t; + +/* + * Values for rpc_gss_error + */ +#define RPC_GSS_ER_SUCCESS 0 /* no error */ +#define RPC_GSS_ER_SYSTEMERROR 1 /* system error */ + +__BEGIN_DECLS + +AUTH *rpc_gss_seccreate(CLIENT *clnt, const char *principal, + const char *mechanism, rpc_gss_service_t service, const char *qop, + rpc_gss_options_req_t *options_req, rpc_gss_options_ret_t *options_ret); +bool_t rpc_gss_set_defaults(AUTH *auth, rpc_gss_service_t service, + const char *qop); +int rpc_gss_max_data_length(AUTH *handle, int max_tp_unit_len); +void rpc_gss_get_error(rpc_gss_error_t *error); + +bool_t rpc_gss_mech_to_oid(const char *mech, gss_OID *oid_ret); +bool_t rpc_gss_oid_to_mech(gss_OID oid, const char **mech_ret); +bool_t rpc_gss_qop_to_num(const char *qop, const char *mech, u_int *num_ret); +const char **rpc_gss_get_mechanisms(void); +const char **rpc_gss_get_mech_info(const char *mech, rpc_gss_service_t *service); +bool_t rpc_gss_get_versions(u_int *vers_hi, u_int *vers_lo); +bool_t rpc_gss_is_installed(const char *mech); + +bool_t rpc_gss_set_svc_name(const char *principal, const char *mechanism, + u_int req_time, u_int program, u_int version); +bool_t rpc_gss_getcred(struct svc_req *req, rpc_gss_rawcred_t **rcred, + rpc_gss_ucred_t **ucred, void **cookie); +bool_t rpc_gss_set_callback(rpc_gss_callback_t *cb); +bool_t rpc_gss_get_principal_name(rpc_gss_principal_t *principal, + const char *mech, const char *name, const char *node, const char *domain); +int rpc_gss_svc_max_data_length(struct svc_req *req, int max_tp_unit_len); + +/* + * Internal interface from the RPC implementation. + */ +bool_t __rpc_gss_wrap(AUTH *auth, void *header, size_t headerlen, + XDR* xdrs, xdrproc_t xdr_args, void *args_ptr); +bool_t __rpc_gss_unwrap(AUTH *auth, XDR* xdrs, xdrproc_t xdr_args, + void *args_ptr); +bool_t __rpc_gss_set_error(int rpc_gss_error, int system_error); + +__END_DECLS + +#endif /* !_RPCSEC_GSS_H */ diff --git a/include/rpc/svc.h b/include/rpc/svc.h index 7ecae0c..8466ef8 100644 --- a/include/rpc/svc.h +++ b/include/rpc/svc.h @@ -127,6 +127,27 @@ typedef struct __rpc_svcxprt { } SVCXPRT; /* + * Interface to server-side authentication flavors. + */ +typedef struct __rpc_svcauth { + struct svc_auth_ops { + int (*svc_ah_wrap)(struct __rpc_svcauth *, XDR *, + xdrproc_t, caddr_t); + int (*svc_ah_unwrap)(struct __rpc_svcauth *, XDR *, + xdrproc_t, caddr_t); + } *svc_ah_ops; + void *svc_ah_private; +} SVCAUTH; + +/* + * Server transport extensions (accessed via xp_p3). + */ +typedef struct __rpc_svcxprt_ext { + int xp_flags; /* versquiet */ + SVCAUTH xp_auth; /* interface to auth methods */ +} SVCXPRT_EXT; + +/* * Service request */ struct svc_req { @@ -184,6 +205,20 @@ struct svc_req { #define SVC_CONTROL(xprt, rq, in) \ (*(xprt)->xp_ops2->xp_control)((xprt), (rq), (in)) +#define SVC_EXT(xprt) \ + ((SVCXPRT_EXT *) xprt->xp_p3) + +#define SVC_AUTH(xprt) \ + (SVC_EXT(xprt)->xp_auth) + +/* + * Operations defined on an SVCAUTH handle + */ +#define SVCAUTH_WRAP(auth, xdrs, xfunc, xwhere) \ + ((auth)->svc_ah_ops->svc_ah_wrap(auth, xdrs, xfunc, xwhere)) +#define SVCAUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \ + ((auth)->svc_ah_ops->svc_ah_unwrap(auth, xdrs, xfunc, xwhere)) + /* * Service registration * @@ -298,6 +333,12 @@ extern int svc_fds; #endif /* def FD_SETSIZE */ /* + * A set of null auth methods used by any authentication protocols + * that don't need to inspect or modify the message body. + */ +extern SVCAUTH _svc_auth_null; + +/* * a small program implemented by the svc_rpc implementation itself; * also see clnt.h for protocol numbers. */ @@ -306,6 +347,8 @@ extern void rpctest_service(void); __END_DECLS __BEGIN_DECLS +extern SVCXPRT *svc_xprt_alloc(void); +extern void svc_xprt_free(SVCXPRT *); extern void svc_getreq(int); extern void svc_getreqset(fd_set *); extern void svc_getreq_common(int); -- cgit v1.1