summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2015-04-22 10:45:05 -0400
committerSteve Dickson <steved@redhat.com>2015-04-29 11:40:32 -0400
commitcf53e9c577cced8c670b13c17c337cc4ad42ff2b (patch)
tree1ad5bb02a76934f7284a0240cdf33ef68adb0d90
parent966ec78061543c83d6a664a30cbe26aac6fa9d6b (diff)
downloadti-rpc-cf53e9c577cced8c670b13c17c337cc4ad42ff2b.tar.gz
Add client-side rpc_gss_*() APIs
Introduce new client-side RPCSEC API functions that match the same libtirpc API in FreeBSD and Solaris. This includes rpc_gss_seccreate(3t), rpc_gss_set_defaults(3t), and rpc_gss_max_data_length(3t). The man pages, written by Doug Rabson, come from FreeBSD, with some adjustments by me. The new code was written from scratch based on FreeBSD's implementation, but adapted to invoke the existing legacy U-M APIs in our implementation. We will continue to provide the legaacy APIs until API consumers are switched to the new ones. FreeBSD never had the legacy U-M GSS APIs. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Steve Dickson <steved@redhat.com>
-rw-r--r--man/Makefile.am4
-rw-r--r--man/rpc_gss_max_data_length.3t61
-rw-r--r--man/rpc_gss_seccreate.3t109
-rw-r--r--man/rpc_gss_set_defaults.3t67
-rw-r--r--src/auth_gss.c242
5 files changed, 481 insertions, 2 deletions
diff --git a/man/Makefile.am b/man/Makefile.am
index 66647f0..366c650 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -10,7 +10,9 @@ GENERIC_MANS = rpc.3t rpc_xdr.3t
RPCSEC_MANS = rpcsec_gss.3t rpc_gss_get_error.3t \
rpc_gss_get_mechanisms.3t rpc_gss_get_mech_info.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_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
dist_man5_MANS = netconfig.5
dist_man3_MANS = $(LOOKUP_MANS) $(NETCONFIG_MANS) \
diff --git a/man/rpc_gss_max_data_length.3t b/man/rpc_gss_max_data_length.3t
new file mode 100644
index 0000000..fa7027a
--- /dev/null
+++ b/man/rpc_gss_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_MAX_DATA_LENGTH 3
+.Os
+.Sh NAME
+.Nm rpc_gss_max_data_length
+.Nd "calculate maximum data size"
+.Sh SYNOPSIS
+.In rpc/rpcsec_gss.h
+.Ft int
+.Fn rpc_gss_max_data_length "AUTH *auth" "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 auth
+A handle to a RPCSEC_GSS security context
+.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_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/man/rpc_gss_seccreate.3t b/man/rpc_gss_seccreate.3t
new file mode 100644
index 0000000..9f526a6
--- /dev/null
+++ b/man/rpc_gss_seccreate.3t
@@ -0,0 +1,109 @@
+.\" 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_SECCREATE 3
+.Os
+.Sh NAME
+.Nm rpc_gss_seccreate
+.Nd "create a security context using the RPCSEC_GSS protocol"
+.Sh SYNOPSIS
+.In rpc/rpcsec_gss.h
+.Ft AUTH *
+.Fo rpc_gss_seccreate
+.Fa "CLIENT *clnt"
+.Fa "const char *principal"
+.Fa "const char *mechanism"
+.Fa "rpc_gss_service_t service"
+.Fa "const char *qop"
+.Fa "rpc_gss_options_req_t *options_req"
+.Fa "rpc_gss_options_ret_t *options_ret"
+.Fc
+.Sh DESCRIPTION
+This function is used to establish a security context between an
+application and a remote peer using the RPSEC_GSS protocol.
+.Sh PARAMETERS
+.Bl -tag -width "options_req"
+.It clnt
+An RPC handle which is connected to the remote peer
+.It principal
+The name of the service principal on the remote peer.
+For instance, a principal such as
+.Qq nfs@server.example.com
+might be used by an application which needs to contact an NFS server
+.It mechanism
+The desired mechanism for this security context.
+The value of mechanism should be the name of one of the security
+mechanisms listed in /etc/gss/mech.
+.It service
+Type of service requested.
+.Bl -tag -width "rpc_gss_svc_integrity"
+.It rpc_gss_svc_default
+The default - typically the same as
+.Dv rpc_gss_svc_none .
+.It rpc_gss_svc_none
+RPC headers only are integrity protected by a checksum.
+.It rpc_gss_svc_integrity
+RPC headers and data are integrity protected by a checksum.
+.It rpc_gss_svc_privacy
+RPC headers are integrity protected by a checksum and data is encrypted.
+.El
+.It qop
+Desired quality of protection or NULL for the default.
+Available values are listed in /etc/gss/qop
+.It options_req
+Extra security context options to be passed to the underlying GSS-API
+mechanism.
+Pass
+.Dv NULL
+to supply default values.
+.It options_ret
+Various values returned by the underlying GSS-API mechanism.
+Pass
+.Dv NULL
+if these values are not required.
+.El
+.Sh RETURN VALUES
+If the security context was created successfully, a pointer to an
+.Vt AUTH
+structure that represents the context is returned.
+To use this security context for subsequent RPC calls, set
+.Va clnt->cl_auth
+to this value.
+.Sh AVAILABILITY
+The
+.Fn rpc_gss_seccreate
+function is part of libtirpc.
+.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr gssapi 3 ,
+.Xr mech 5 ,
+.Xr qop 5 ,
+.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_defaults.3t b/man/rpc_gss_set_defaults.3t
new file mode 100644
index 0000000..471a829
--- /dev/null
+++ b/man/rpc_gss_set_defaults.3t
@@ -0,0 +1,67 @@
+.\" 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_DEFAULTS 3
+.Os
+.Sh NAME
+.Nm rpc_gss_set_defaults
+.Nd "set service and quality of protection"
+.Sh SYNOPSIS
+.In rpc/rpcsec_gss.h
+.Ft bool_t
+.Fo rpc_gss_set_defaults
+.Fa "AUTH *auth"
+.Fa "rpc_gss_service_t service"
+.Fa "const char *qop"
+.Fc
+.Sh DESCRIPTION
+Set the service and quality of protection to be used for RPC requests.
+The new values apply for the rest of the lifetime of the context
+(unless changed again with this function).
+.Sh PARAMETERS
+.Bl -tag -width ".It service"
+.It service
+The service type to use for subsequent RPC requests
+.It qop
+The quality of protection to use or NULL for the default
+.El
+.Sh RETURN VALUES
+Returns
+.Dv TRUE
+if the values were set
+.Sh AVAILABILITY
+The
+.Fn rpc_gss_set_defaults
+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/auth_gss.c b/src/auth_gss.c
index bab591c..3b79311 100644
--- a/src/auth_gss.c
+++ b/src/auth_gss.c
@@ -45,9 +45,9 @@
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_gss.h>
+#include <rpc/rpcsec_gss.h>
#include <rpc/clnt.h>
#include <netinet/in.h>
-#include <gssapi/gssapi.h>
#include "debug.h"
@@ -60,6 +60,9 @@ static void authgss_destroy_context(AUTH *);
static bool_t authgss_wrap(AUTH *, XDR *, xdrproc_t, caddr_t);
static bool_t authgss_unwrap(AUTH *, XDR *, xdrproc_t, caddr_t);
+void rpc_gss_set_error(int);
+void rpc_gss_clear_error(void);
+bool_t rpc_gss_oid_to_mech(rpc_gss_OID, char **);
/*
* from mit-krb5-1.2.1 mechglue/mglueP.h:
@@ -667,3 +670,240 @@ authgss_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
gd->ctx, gd->sec.qop,
gd->sec.svc, gd->gc.gc_seq));
}
+
+static AUTH *
+_rpc_gss_seccreate_error(int system_error)
+{
+ rpc_gss_set_error(system_error);
+ return NULL;
+}
+
+/*
+ * External API: Create a GSS security context for this "clnt"
+ *
+ * clnt: a valid RPC CLIENT structure
+ * principal: NUL-terminated C string containing GSS principal
+ * mechanism: NUL-terminated C string containing GSS mechanism name
+ * service: GSS security value to use
+ * qop: NUL-terminated C string containing QOP name
+ * req: pointer to additional request parameters, or NULL
+ * ret: pointer to additional results, or NULL
+ *
+ * Returns pointer to a filled in RPC AUTH structure or NULL.
+ * Caller must free returned structure with AUTH_DESTROY.
+ */
+AUTH *
+rpc_gss_seccreate(CLIENT *clnt, char *principal, char *mechanism,
+ rpc_gss_service_t service, char *qop,
+ rpc_gss_options_req_t *req, rpc_gss_options_ret_t *ret)
+{
+ rpc_gss_options_ret_t options_ret;
+ OM_uint32 maj_stat, min_stat;
+ struct rpc_gss_sec sec = {
+ .req_flags = GSS_C_MUTUAL_FLAG,
+ .cred = GSS_C_NO_CREDENTIAL,
+ };
+ struct rpc_gss_data *gd;
+ AUTH *auth, *save_auth;
+ gss_buffer_desc sname;
+
+ if (clnt == NULL || principal == NULL)
+ return _rpc_gss_seccreate_error(EINVAL);
+
+ if (rpc_gss_mech_to_oid(mechanism, &sec.mech) == FALSE)
+ return NULL;
+
+ sec.qop = GSS_C_QOP_DEFAULT;
+ if (qop != NULL) {
+ u_int qop_num;
+ if (rpc_gss_qop_to_num(qop, mechanism, &qop_num) == FALSE)
+ return NULL;
+ sec.qop = qop_num;
+ }
+
+ switch (service) {
+ case rpcsec_gss_svc_none:
+ sec.svc = RPCSEC_GSS_SVC_NONE;
+ break;
+ case rpcsec_gss_svc_integrity:
+ sec.svc = RPCSEC_GSS_SVC_INTEGRITY;
+ break;
+ case rpcsec_gss_svc_privacy:
+ sec.svc = RPCSEC_GSS_SVC_PRIVACY;
+ break;
+ case rpcsec_gss_svc_default:
+ sec.svc = RPCSEC_GSS_SVC_INTEGRITY;
+ break;
+ default:
+ return _rpc_gss_seccreate_error(ENOENT);
+ }
+
+ if (req != NULL) {
+ sec.req_flags = req->req_flags;
+ sec.cred = req->my_cred;
+ }
+
+ if (ret == NULL)
+ ret = &options_ret;
+ memset(ret, 0, sizeof(*ret));
+
+ auth = calloc(1, sizeof(*auth));
+ gd = calloc(1, sizeof(*gd));
+ if (auth == NULL || gd == NULL) {
+ free(gd);
+ free(auth);
+ return _rpc_gss_seccreate_error(ENOMEM);
+ }
+
+ sname.value = principal;
+ sname.length = strlen(principal);
+ maj_stat = gss_import_name(&min_stat, &sname,
+ (gss_OID)GSS_C_NT_HOSTBASED_SERVICE,
+ &gd->name);
+ if (maj_stat != GSS_S_COMPLETE) {
+ ret->major_status = maj_stat;
+ ret->minor_status = min_stat;
+ free(gd);
+ free(auth);
+ return _rpc_gss_seccreate_error(ENOMEM);
+ }
+
+ gd->clnt = clnt;
+ gd->ctx = GSS_C_NO_CONTEXT;
+ gd->sec = sec;
+
+ gd->gc.gc_v = RPCSEC_GSS_VERSION;
+ gd->gc.gc_proc = RPCSEC_GSS_INIT;
+ gd->gc.gc_svc = sec.svc;
+
+ auth->ah_ops = &authgss_ops;
+ auth->ah_private = (caddr_t)gd;
+
+ save_auth = clnt->cl_auth;
+ clnt->cl_auth = auth;
+
+ if (authgss_refresh(auth, NULL) == FALSE) {
+ authgss_destroy(auth);
+ auth = NULL;
+ } else {
+ rpc_gss_clear_error();
+ auth_get(auth);
+ }
+
+ clnt->cl_auth = save_auth;
+
+ return auth;
+}
+
+/*
+ * External API: Modify an AUTH's service and QOP settings
+ *
+ * auth: a valid RPC AUTH structure
+ * service: GSS security value to use
+ * qop: NUL-terminated C string containing QOP name
+ *
+ * Returns TRUE if successful, otherwise FALSE is returned.
+ */
+bool_t
+rpc_gss_set_defaults(AUTH *auth, rpc_gss_service_t service, char *qop)
+{
+ struct rpc_gss_data *gd;
+ char *mechanism;
+ u_int qop_num;
+
+ if (auth == NULL) {
+ rpc_gss_set_error(EINVAL);
+ return FALSE;
+ }
+
+ gd = AUTH_PRIVATE(auth);
+ if (gd == NULL) {
+ rpc_gss_set_error(EINVAL);
+ return FALSE;
+ }
+
+ if (rpc_gss_oid_to_mech(gd->sec.mech, &mechanism) == FALSE)
+ return FALSE;
+
+ qop_num = GSS_C_QOP_DEFAULT;
+ if (qop != NULL) {
+ if (rpc_gss_qop_to_num(qop, mechanism, &qop_num) == FALSE)
+ return FALSE;
+ }
+
+ switch (service) {
+ case rpcsec_gss_svc_none:
+ gd->gc.gc_svc = gd->sec.svc = RPCSEC_GSS_SVC_NONE;
+ break;
+ case rpcsec_gss_svc_integrity:
+ gd->gc.gc_svc = gd->sec.svc = RPCSEC_GSS_SVC_INTEGRITY;
+ break;
+ case rpcsec_gss_svc_privacy:
+ gd->gc.gc_svc = gd->sec.svc = RPCSEC_GSS_SVC_PRIVACY;
+ break;
+ case rpcsec_gss_svc_default:
+ gd->gc.gc_svc = gd->sec.svc = RPCSEC_GSS_SVC_INTEGRITY;
+ break;
+ default:
+ rpc_gss_set_error(ENOENT);
+ return FALSE;
+ }
+
+ gd->sec.qop = (gss_qop_t)qop_num;
+ rpc_gss_clear_error();
+ return TRUE;
+}
+
+/*
+ * External API: Return maximum data size for a security mechanism and transport
+ *
+ * auth: a valid RPC AUTH structure
+ * 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_max_data_length(AUTH *auth, int maxlen)
+{
+ OM_uint32 max_input_size, maj_stat, min_stat;
+ struct rpc_gss_data *gd;
+ int conf_req_flag;
+ int result;
+
+ if (auth == NULL) {
+ rpc_gss_set_error(EINVAL);
+ return 0;
+ }
+
+ gd = AUTH_PRIVATE(auth);
+ if (gd == NULL) {
+ rpc_gss_set_error(EINVAL);
+ return 0;
+ }
+
+ switch (gd->sec.svc) {
+ case RPCSEC_GSS_SVC_NONE:
+ rpc_gss_clear_error();
+ return maxlen;
+ case RPCSEC_GSS_SVC_INTEGRITY:
+ conf_req_flag = 0;
+ break;
+ case RPCSEC_GSS_SVC_PRIVACY:
+ conf_req_flag = 1;
+ break;
+ default:
+ rpc_gss_set_error(ENOENT);
+ 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;
+ rpc_gss_clear_error();
+ return result;
+}