diff options
-rw-r--r-- | man/Makefile.am | 4 | ||||
-rw-r--r-- | man/rpc_gss_get_principal_name.3t | 79 | ||||
-rw-r--r-- | man/rpc_gss_getcred.3t | 82 | ||||
-rw-r--r-- | man/rpc_gss_set_callback.3t | 112 | ||||
-rw-r--r-- | man/rpc_gss_set_svc_name.3t | 84 | ||||
-rw-r--r-- | man/rpc_gss_svc_max_data_length.3t | 61 | ||||
-rw-r--r-- | src/svc_auth_gss.c | 370 |
7 files changed, 782 insertions, 10 deletions
diff --git a/man/Makefile.am b/man/Makefile.am index 366c650..cf510e7 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -12,7 +12,9 @@ RPCSEC_MANS = rpcsec_gss.3t rpc_gss_get_error.3t \ rpc_gss_get_versions.3t rpc_gss_is_installed.3t \ rpc_gss_mech_to_oid.3t rpc_gss_qop_to_num.3t \ rpc_gss_max_data_length.3t rpc_gss_seccreate.3t \ - rpc_gss_set_defaults.3t + rpc_gss_set_defaults.3t rpc_gss_getcred.3t \ + rpc_gss_get_principal_name.3t rpc_gss_set_callback.3t \ + rpc_gss_set_svc_name.3t rpc_gss_svc_max_data_length.3t dist_man5_MANS = netconfig.5 dist_man3_MANS = $(LOOKUP_MANS) $(NETCONFIG_MANS) \ diff --git a/man/rpc_gss_get_principal_name.3t b/man/rpc_gss_get_principal_name.3t new file mode 100644 index 0000000..ba04239 --- /dev/null +++ b/man/rpc_gss_get_principal_name.3t @@ -0,0 +1,79 @@ +.\" Copyright (c) 2008 Isilon Inc http://www.isilon.com/ +.\" Authors: Doug Rabson <dfr@rabson.org> +.\" Developed with Red Inc: Alfred Perlstein <alfred@FreeBSD.org> +.\" +.\" 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$ +.Dd January 26, 2010 +.Dt RPC_GSS_GET_PRINCIPAL_NAME 3 +.Os +.Sh NAME +.Nm rpc_gss_get_principal_name +.Nd "Get a principal name" +.Sh SYNOPSIS +.In rpc/rpcsec_gss.h +.Ft bool_t +.Fo rpc_gss_get_principal_name +.Fa "rpc_gss_principal_t *principal" +.Fa "const char *mech" +.Fa "const char *name" +.Fa "const char *node" +.Fa "const char *domain" +.Fc +.Sh DESCRIPTION +This function can be used to generate a client principal name from +various strings. +.Sh PARAMETERS +.Bl -tag -width ".It principal" +.It principal +If the principal is created successfully, +.Fa *principal +will be set to point at the new principal in GSS-API exported name form +.It mech +The name of the mechanism for this principal +.It name +The name part of the principal +.It node +If non-null, the hostname or instance part of the principal +.It domain +If non-null, the domain or realm part of the principal +.El +.Sh RETURN VALUES +Returns +.Dv TRUE +if the principal was created or +.Dv FALSE +otherwise +.Sh AVAILABILITY +The +.Fn rpc_gss_get_principal_name +function is part of libtirpc. +.Sh SEE ALSO +.Xr rpc 3 , +.Xr gssapi 3 , +.Xr gss_export_name 3 , +.Xr rpcsec_gss 3 +.Sh AUTHORS +This +manual page was written by +.An Doug Rabson Aq dfr@FreeBSD.org . diff --git a/man/rpc_gss_getcred.3t b/man/rpc_gss_getcred.3t new file mode 100644 index 0000000..8589f08 --- /dev/null +++ b/man/rpc_gss_getcred.3t @@ -0,0 +1,82 @@ +.\" Copyright (c) 2008 Isilon Inc http://www.isilon.com/ +.\" Authors: Doug Rabson <dfr@rabson.org> +.\" Developed with Red Inc: Alfred Perlstein <alfred@FreeBSD.org> +.\" +.\" 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$ +.Dd January 26, 2010 +.Dt RPC_GSS_GETCRED 3 +.Os +.Sh NAME +.Nm rpc_gss_getcred +.Nd "Get authorization information for an RPC request" +.Sh SYNOPSIS +.In rpc/rpcsec_gss.h +.Ft AUTH * +.Fo rpc_gss_getcred +.Fa "struct svc_req *req" +.Fa "rpc_gss_rawcred_t **rcred" +.Fa "rpc_gss_ucred_t **ucred" +.Fa "void **cookie" +.Fc +.Sh DESCRIPTION +This function returns the RPCSEC_GSS authenticated credentials +associated with an RPC request. +.Sh PARAMETERS +.Bl -tag -width ".It cookie" +.It req +The RPC request to query +.It rcred +If non-null, +.Fa *rcred +is set to point at the raw credentials for this request +.It ucred +.It rcred +If non-null, +.Fa *ucred +is set to point at the corresponding unix credentials +.It cookie +If non-null, +.Fa *cookie +is set to the cookie value returned by a callback function registered with +.Fn rpc_gss_set_callback +.El +.Sh RETURN VALUES +Returns +.Dv TRUE +if successful, +.Dv FALSE +otherwise. +.Sh AVAILABILITY +The +.Fn rpc_gss_getcred +function is part of libtirpc. +.Sh SEE ALSO +.Xr rpc 3 , +.Xr gssapi 3 , +.Xr rpc_gss_set_callback 3 , +.Xr rpcsec_gss 3 +.Sh AUTHORS +This +manual page was written by +.An Doug Rabson Aq dfr@FreeBSD.org . diff --git a/man/rpc_gss_set_callback.3t b/man/rpc_gss_set_callback.3t new file mode 100644 index 0000000..ee4ebdf --- /dev/null +++ b/man/rpc_gss_set_callback.3t @@ -0,0 +1,112 @@ +.\" Copyright (c) 2008 Isilon Inc http://www.isilon.com/ +.\" Authors: Doug Rabson <dfr@rabson.org> +.\" Developed with Red Inc: Alfred Perlstein <alfred@FreeBSD.org> +.\" +.\" 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$ +.Dd January 26, 2010 +.Dt RPC_GSS_SET_CALLBACK 3 +.Os +.Sh NAME +.Nm rpc_gss_set_callback +.Nd "Register a security context creation callback" +.Sh SYNOPSIS +.In rpc/rpcsec_gss.h +.Ft bool_t +.Fo (*callback) +.Fa "struct svc_req *req" +.Fa "gss_cred_id_t deleg" +.Fa "gss_ctx_id_t gss_context" +.Fa "rpc_gss_lock_t *lock" +.Fa "void **cookie" +.Fc +.Ft bool_t +.Fn rpc_gss_set_callback "rpc_gss_callback_t *cb" +.Sh DESCRIPTION +Register a function which will be called when new security contexts +are created on a server. +This function will be called on the first RPC request which uses that +context and has the opportunity of rejecting the request (for instance +after matching the request credentials to an access control list). +To accept the new security context, the callback should return +.Dv TRUE , +otherwise +.Dv FALSE . +If the callback accepts a context, it becomes responsible for the +lifetime of the delegated client credentials (if any). +.Pp +It is also possible to 'lock' the values of service and quality of +protection used by the context. +If a context is locked, any subsequent requests which use different +values for service and quality of protection will be rejected. +.Sh PARAMETERS +.Bl -tag -width ".It gss_context" +.It cb +A structure containing the RPC program and version for this callback +and a function which will be called when new contexts are created for +the given RPC program and version +.It req +The RPC request using the new context +.It deleg +GSS-API delegated credentials (if any) +.It gss_context +The GSS-API context +.It lock +A structure used to enforce a particular QOP and service. Set +.Fa lock->locked +to +.Dv TRUE +to lock the service and QOP values +.It cookie +The callback function may set +.Fa *cookie +to any pointer sized value. +This value can be accessed during the lifetime of the context via +.Fn rpc_gss_getcred . +.El +.Sh RETURN VALUES +Returns +.Dv TRUE +if the callback was registered successfully or +.Dv FALSE +otherwise +.Sh AVAILABILITY +The +.Fn rpc_gss_set_callback +function is part of libtirpc. +.Sh SEE ALSO +.Xr rpc 3 , +.Xr gssapi 3 , +.Xr rpc_gss_getcred 3 +.Xr rpcsec_gss 3 +.Sh AUTHORS +This +manual page was written by +.An Doug Rabson Aq dfr@FreeBSD.org . +.Sh BUGS +There is no mechanism for informing a server when a security context +has been deleted. +This makes it difficult to allocate resources (e.g. to return via the +callback's +.Fa cookie +argument). diff --git a/man/rpc_gss_set_svc_name.3t b/man/rpc_gss_set_svc_name.3t new file mode 100644 index 0000000..b895920 --- /dev/null +++ b/man/rpc_gss_set_svc_name.3t @@ -0,0 +1,84 @@ +.\" Copyright (c) 2008 Isilon Inc http://www.isilon.com/ +.\" Authors: Doug Rabson <dfr@rabson.org> +.\" Developed with Red Inc: Alfred Perlstein <alfred@FreeBSD.org> +.\" +.\" 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$ +.Dd January 26, 2010 +.Dt RPC_GSS_SET_SVC_NAME 3 +.Os +.Sh NAME +.Nm rpc_gss_set_svc_name +.Nd "Associate a GSS-API service principal with an RPC service" +.Sh SYNOPSIS +.In rpc/rpcsec_gss.h +.Ft bool_t +.Fo rpc_gss_set_svc_name +.Fa "const char *principal" +.Fa "const char *mechanism" +.Fa "u_int req_time" +.Fa "u_int program" +.Fa "u_int version" +.Fc +.Sh DESCRIPTION +This function registers a service principal which will be used to +authenticate RPCSEC_GSS security contexts for a given RPC program and +version. +.Sh PARAMETERS +.Bl -tag -width ".It mechanism" +.It principal +A string representing the service principal in the form +.Qq service@hostname +.It mechanism +The name of the security mechanism +.It req_time +The time in seconds that the service credentials should remain +valid. +See +.Xr gss_acquire_cred 3 +for more details. +principal. +.It program +RPC program number for this service +.It version +RPC program version for this service +.El +.Sh RETURN VALUES +Returns +.Dv TRUE +if the service principal was registered or +.Dv FALSE +otherwise. +.Sh AVAILABILITY +The +.Fn rpc_gss_set_svc_name +function is part of libtirpc. +.Sh SEE ALSO +.Xr rpc 3 , +.Xr gssapi 3 , +.Xr gss_acquire_cred 3 , +.Xr rpcsec_gss 3 +.Sh AUTHORS +This +manual page was written by +.An Doug Rabson Aq dfr@FreeBSD.org . diff --git a/man/rpc_gss_svc_max_data_length.3t b/man/rpc_gss_svc_max_data_length.3t new file mode 100644 index 0000000..4b89716 --- /dev/null +++ b/man/rpc_gss_svc_max_data_length.3t @@ -0,0 +1,61 @@ +.\" Copyright (c) 2008 Isilon Inc http://www.isilon.com/ +.\" Authors: Doug Rabson <dfr@rabson.org> +.\" Developed with Red Inc: Alfred Perlstein <alfred@FreeBSD.org> +.\" +.\" 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$ +.Dd January 26, 2010 +.Dt RPC_GSS_SVC_MAX_DATA_LENGTH 3 +.Os +.Sh NAME +.Nm rpc_gss_svc_max_data_length +.Nd "calculate maximum data size" +.Sh SYNOPSIS +.In rpc/rpcsec_gss.h +.Ft int +.Fn rpc_gss_svc_max_data_length "struct svc_req *req" "int max_tp_unit_len" +.Sh DESCRIPTION +Calculate the maximum message size that will fit into a packet of size +.Fa max_tp_unit_len , +given the current service and QoP setting. +.Sh PARAMETERS +.Bl -tag -width ".It max_tp_unit_len" +.It req +An RPC request +.It max_tp_unit_len +Maximum packet size of the underlying transport protocol +.El +.Sh RETURN VALUES +The maximum message size that can be encoded +.Sh AVAILABILITY +The +.Fn rpc_gss_svc_max_data_length +function is part of libtirpc. +.Sh SEE ALSO +.Xr rpc 3 , +.Xr gssapi 3 , +.Xr rpcsec_gss 3 +.Sh AUTHORS +This +manual page was written by +.An Doug Rabson Aq dfr@FreeBSD.org . diff --git a/src/svc_auth_gss.c b/src/svc_auth_gss.c index 155c8de..f5165b5 100644 --- a/src/svc_auth_gss.c +++ b/src/svc_auth_gss.c @@ -34,14 +34,28 @@ */ +#include <sys/types.h> + +#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <pwd.h> +#include <grp.h> + #include <rpc/rpc.h> -#include <gssapi/gssapi.h> +#include <rpc/rpcsec_gss.h> + +#include <gssapi/gssapi_ext.h> + +#define UNUSED(x) UNUSED_ ## x __attribute__((unused)) extern SVCAUTH svc_auth_none; +/* Internal only */ +bool_t rpc_gss_oid_to_mech(rpc_gss_OID, char **); +bool_t rpc_gss_num_to_qop(char *, u_int, char **); + /* * from mit-krb5-1.2.1 mechglue/mglueP.h: * Array of context IDs typed by mechanism OID @@ -73,6 +87,10 @@ struct svc_rpc_gss_data { u_int seqlast; /* last sequence number */ u_int32_t seqmask; /* bitmask of seqnums */ gss_name_t client_name; /* unparsed name string */ + rpc_gss_rawcred_t rcred; /* raw credential */ + rpc_gss_ucred_t ucred; /* cooked credential */ + gid_t gids[NGRPS]; /* list of groups */ + void * cookie; /* callback cookie */ }; #define SVCAUTH_PRIVATE(auth) \ @@ -80,7 +98,8 @@ struct svc_rpc_gss_data { /* Global server credentials. */ static gss_cred_id_t _svcauth_gss_creds; -static gss_name_t _svcauth_gss_name = NULL; +static gss_name_t _svcauth_gss_name = GSS_C_NO_NAME; +static char * _svcauth_svc_name = NULL; bool_t svcauth_gss_set_svc_name(gss_name_t name) @@ -89,7 +108,7 @@ svcauth_gss_set_svc_name(gss_name_t name) gss_log_debug("in svcauth_gss_set_svc_name()"); - if (_svcauth_gss_name != NULL) { + if (_svcauth_gss_name != GSS_C_NO_NAME) { maj_stat = gss_release_name(&min_stat, &_svcauth_gss_name); if (maj_stat != GSS_S_COMPLETE) { @@ -97,7 +116,7 @@ svcauth_gss_set_svc_name(gss_name_t name) maj_stat, min_stat); return (FALSE); } - _svcauth_gss_name = NULL; + _svcauth_gss_name = GSS_C_NO_NAME; } maj_stat = gss_duplicate_name(&min_stat, name, &_svcauth_gss_name); @@ -138,14 +157,14 @@ svcauth_gss_import_name(char *service) } static bool_t -svcauth_gss_acquire_cred(void) +svcauth_gss_acquire_cred(u_int req_time, gss_OID_set_desc *oid_set) { OM_uint32 maj_stat, min_stat; gss_log_debug("in svcauth_gss_acquire_cred()"); - maj_stat = gss_acquire_cred(&min_stat, _svcauth_gss_name, 0, - GSS_C_NULL_OID_SET, GSS_C_ACCEPT, + maj_stat = gss_acquire_cred(&min_stat, _svcauth_gss_name, req_time, + oid_set, GSS_C_ACCEPT, &_svcauth_gss_creds, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { @@ -176,6 +195,52 @@ svcauth_gss_release_cred(void) return (TRUE); } +static rpc_gss_service_t +_rpc_gss_svc_to_service(rpc_gss_svc_t svc) +{ + switch (svc) { + case RPCSEC_GSS_SVC_NONE: + return rpcsec_gss_svc_none; + case RPCSEC_GSS_SVC_INTEGRITY: + return rpcsec_gss_svc_integrity; + case RPCSEC_GSS_SVC_PRIVACY: + return rpcsec_gss_svc_privacy; + } + return rpcsec_gss_svc_default; +} + +static bool_t +_rpc_gss_fill_in_creds(struct svc_rpc_gss_data *gd, struct rpc_gss_cred *gc) +{ + rpc_gss_rawcred_t *rcred = &gd->rcred; + OM_uint32 maj_stat, min_stat; + gss_buffer_desc buf; + + rcred->version = gc->gc_v; + if (!rpc_gss_oid_to_mech(gd->sec.mech, &rcred->mechanism)) + return FALSE; + rcred->service = _rpc_gss_svc_to_service(gd->sec.svc); + maj_stat = gss_export_name(&min_stat, gd->client_name, &buf); + if (maj_stat != GSS_S_COMPLETE) { + gss_log_status("gss_export_name", maj_stat, min_stat); + return FALSE; + } + + rcred->client_principal = calloc(1, sizeof(rpc_gss_principal_t) + + buf.length); + if (rcred->client_principal == NULL) { + (void)gss_release_buffer(&min_stat, &buf); + return FALSE; + } + rcred->client_principal->len = buf.length; + (void)memcpy(rcred->client_principal->name, buf.value, buf.length); + (void)gss_release_buffer(&min_stat, &buf); + + rcred->svc_principal = _svcauth_svc_name; + + return TRUE; +} + static bool_t svcauth_gss_accept_sec_context(struct svc_req *rqst, struct rpc_gss_init_res *gr) @@ -248,6 +313,9 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, maj_stat, min_stat); return (FALSE); } + if (!_rpc_gss_fill_in_creds(gd, gc)) + return (FALSE); + #ifdef HAVE_KRB5 { gss_buffer_desc mechname; @@ -460,12 +528,12 @@ _svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) if (rqst->rq_proc != NULLPROC) return (AUTH_FAILED); /* XXX ? */ - if (_svcauth_gss_name == NULL) { + if (_svcauth_gss_name == GSS_C_NO_NAME) { if (!svcauth_gss_import_name("nfs")) return (AUTH_FAILED); } - if (!svcauth_gss_acquire_cred()) + if (!svcauth_gss_acquire_cred(0, GSS_C_NULL_OID_SET)) return (AUTH_FAILED); if (!svcauth_gss_accept_sec_context(rqst, &gr)) @@ -535,6 +603,8 @@ svcauth_gss_destroy(SVCAUTH *auth) if (gd->client_name) gss_release_name(&min_stat, &gd->client_name); + if (gd->rcred.client_principal != NULL) + free(gd->rcred.client_principal); mem_free(gd, sizeof(*gd)); mem_free(auth, sizeof(*auth)); @@ -595,3 +665,285 @@ svcauth_gss_get_principal(SVCAUTH *auth) return (pname); } + +/* + * External API: Return maximum data size for a security mechanism and transport + * + * rqst: an incoming RPC request + * maxlen: transport's maximum data size, in bytes + * + * Returns maximum data size given transformations done by current + * security setting of "auth", in bytes, or zero if that value + * cannot be determined. + */ +int +rpc_gss_svc_max_data_length(struct svc_req *rqst, int maxlen) +{ + OM_uint32 max_input_size, maj_stat, min_stat; + struct svc_rpc_gss_data *gd; + int conf_req_flag; + int result; + + if (!rqst) + return 0; + + gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth); + + switch (gd->rcred.service) { + case rpcsec_gss_svc_none: + return maxlen; + case rpcsec_gss_svc_default: + case rpcsec_gss_svc_integrity: + conf_req_flag = 0; + break; + case rpcsec_gss_svc_privacy: + conf_req_flag = 1; + break; + default: + return 0; + } + + result = 0; + maj_stat = gss_wrap_size_limit(&min_stat, gd->ctx, conf_req_flag, + gd->sec.qop, maxlen, &max_input_size); + if (maj_stat == GSS_S_COMPLETE) + if ((int)max_input_size > 0) + result = (int)max_input_size; + return result; +} + +/* + * External API: Set server's GSS principal + * + * principal: NUL-terminated C string containing GSS principal + * mechanism: NUL-terminated C string containing GSS mechanism name + * req_time: time in seconds until credential expires + * program: program number of the RPC service + * version: version number of the RPC service + * + * Returns TRUE if successful, otherwise FALSE is returned. + */ +bool_t +rpc_gss_set_svc_name(char *principal, char *mechanism, u_int req_time, + u_int UNUSED(program), u_int UNUSED(version)) +{ + gss_OID_set_desc oid_set; + rpc_gss_OID oid; + char *save; + + if (principal == NULL) + return FALSE; + save = strdup(principal); + if (save == NULL) + return FALSE; + + if (!rpc_gss_mech_to_oid(mechanism, &oid)) + goto out_err; + oid_set.count = 1; + oid_set.elements = (gss_OID)oid; + + if (!svcauth_gss_import_name(principal)) + goto out_err; + if (!svcauth_gss_acquire_cred(req_time, &oid_set)) + goto out_err; + + free(_svcauth_svc_name); + _svcauth_svc_name = save; + return TRUE; + +out_err: + free(save); + return FALSE; +} + +static void +_rpc_gss_fill_in_ucreds(struct svc_rpc_gss_data *gd) +{ + rpc_gss_ucred_t *ucred = &gd->ucred; + OM_uint32 maj_stat, min_stat; + struct passwd pwd, *pw; + long buflen; + uid_t uid; + char *buf; + int len; + + /* default: "nfsnobody" */ + ucred->uid = 65534; + ucred->gid = 65534; + ucred->gidlen = 0; + ucred->gidlist = gd->gids; + + maj_stat = gss_pname_to_uid(&min_stat, gd->client_name, + gd->sec.mech, &uid); + if (maj_stat != GSS_S_COMPLETE) + return; + + buflen = sysconf(_SC_GETPW_R_SIZE_MAX); + if (buflen == -1) + return; + buf = malloc((size_t)buflen); + if (buf == NULL) + return; + + (void)getpwuid_r(uid, &pwd, buf, buflen, &pw); + if (pw == NULL) { + free(buf); + return; + } + + ucred->uid = pw->pw_uid; + ucred->gid = pw->pw_gid; + len = NGRPS; + (void)getgrouplist(pw->pw_name, pw->pw_gid, ucred->gidlist, &len); + ucred->gidlen = len; + + free(buf); +} + +/* + * External API: Retrieve requesting client's GSS credential + * + * rqst: an incoming RPC request + * rcred: address of pointer to fill in, or NULL + * ucred: address of pointer to fill in, or NULL + * cookie: address of pointer to fill in, or NULL + * + * Returns TRUE if successful. "rcred," "ucred," and "cookie" + * are filled in with pointers to the relevant structures. + * Caller must not free the memory returned by this API. + */ +bool_t +rpc_gss_getcred(struct svc_req *rqst, rpc_gss_rawcred_t **rcred, + rpc_gss_ucred_t **ucred, void **cookie) +{ + struct svc_rpc_gss_data *gd; + SVCAUTH *auth; + + if (rqst == NULL) + return FALSE; + + if (rqst->rq_xprt->xp_verf.oa_flavor != RPCSEC_GSS) + return FALSE; + + auth = rqst->rq_xprt->xp_auth; + gd = SVCAUTH_PRIVATE(auth); + + if (rcred != NULL) { + auth->raw_cred = gd->rcred; + auth->raw_cred.service = _rpc_gss_svc_to_service(gd->sec.svc); + (void)rpc_gss_num_to_qop(auth->raw_cred.mechanism, gd->sec.qop, + &auth->raw_cred.qop); + *rcred = &auth->raw_cred; + } + + if (ucred != NULL) { + _rpc_gss_fill_in_ucreds(gd); + *ucred = &gd->ucred; + } + + if (cookie != NULL) + *cookie = gd->cookie; + + return TRUE; +} + +/* + * External API: Register a callback function + * + * callback: callback structure containing function and parameters + * + * Returns TRUE if successful, otherwise FALSE. + * + * "callback" is copied by rpc_gss_set_callback(), and may be freed + * immediately after it returns. + */ +bool_t +rpc_gss_set_callback(rpc_gss_callback_t *callback) +{ + /* not yet supported */ + return FALSE; +} + +/* + * External API: Form a generic rpc_gss_principal + * + * principal: address of buffer to fill in + * mechanism: NUL-terminated C string containing GSS mechanism name + * user_name: NUL-terminated C string containing user or service principal + * node: NUL-terminated C string containing a hostname + * secdomain: NUL-terminated C string containing a security realm + * + * Returns TRUE if successful, otherwise FALSE. Caller must free + * returned "principal" with free(3). + */ +bool_t +rpc_gss_get_principal_name(rpc_gss_principal_t *principal, char *mechanism, + char *user_name, char *node, char *secdomain) +{ + OM_uint32 maj_stat, min_stat; + rpc_gss_principal_t result; + size_t nodelen, secdomlen; + gss_name_t name, mechname; + gss_buffer_desc namebuf; + rpc_gss_OID oid; + + + if (principal == NULL || user_name == NULL || strlen(user_name) == 0) + return FALSE; + if (!rpc_gss_mech_to_oid(mechanism, &oid)) + return FALSE; + + nodelen = 0; + if (node != NULL) + nodelen = strlen(node) + 1; + secdomlen = 0; + if (secdomain != NULL) + secdomlen = strlen(secdomain) + 1; + namebuf.length = strlen(user_name) + nodelen + secdomlen; + namebuf.value = calloc(1, namebuf.length); + if (namebuf.value == NULL) + return FALSE; + (void)strcpy(namebuf.value, user_name); + if (nodelen > 0) { + (void)strcat(namebuf.value, "/"); + (void)strcat(namebuf.value, node); + } + if (secdomlen > 0) { + (void)strcat(namebuf.value, "@"); + (void)strcat(namebuf.value, secdomain); + } + + maj_stat = gss_import_name(&min_stat, &namebuf, + GSS_C_NT_USER_NAME, &name); + free(namebuf.value); + if (maj_stat != GSS_S_COMPLETE) { + gss_log_status("gss_import_name", maj_stat, min_stat); + return FALSE; + } + + maj_stat = gss_canonicalize_name(&min_stat, name, oid, &mechname); + (void)gss_release_name(&min_stat, &name); + if (maj_stat != GSS_S_COMPLETE) { + gss_log_status("gss_canonicalize_name", maj_stat, min_stat); + return FALSE; + } + + maj_stat = gss_export_name(&min_stat, mechname, &namebuf); + (void)gss_release_name(&min_stat, &mechname); + if (maj_stat != GSS_S_COMPLETE) { + gss_log_status("gss_export_name", maj_stat, min_stat); + return FALSE; + } + + result = calloc(1, sizeof(*result) + namebuf.length); + if (result == NULL) { + (void)gss_release_buffer(&min_stat, &namebuf); + return FALSE; + } + result->len = namebuf.length; + (void)memcpy(result->name, namebuf.value, namebuf.length); + (void)gss_release_buffer(&min_stat, &namebuf); + + *principal = result; + return TRUE; +} |