summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/Makefile.am4
-rw-r--r--man/rpc_gss_get_principal_name.3t79
-rw-r--r--man/rpc_gss_getcred.3t82
-rw-r--r--man/rpc_gss_set_callback.3t112
-rw-r--r--man/rpc_gss_set_svc_name.3t84
-rw-r--r--man/rpc_gss_svc_max_data_length.3t61
-rw-r--r--src/svc_auth_gss.c370
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;
+}