Path: blob/main/tools/regression/rpcsec_gss/rpctest.c
39530 views
/*-1* Copyright (c) 2008 Isilon Inc http://www.isilon.com/2* Authors: Doug Rabson <[email protected]>3* Developed with Red Inc: Alfred Perlstein <[email protected]>4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#ifdef __FreeBSD__28#include <sys/cdefs.h>29#else30#define __unused31#endif3233#include <ctype.h>34#include <err.h>35#include <netdb.h>36#include <stdio.h>37#include <stdlib.h>38#include <string.h>39#include <unistd.h>4041#include <rpc/rpc.h>42#include <rpc/rpcsec_gss.h>4344static rpc_gss_principal_t server_acl = NULL;4546static void47usage(void)48{49printf("rpctest client | server\n");50exit(1);51}5253static void54print_principal(rpc_gss_principal_t principal)55{56int i, len, n;57uint8_t *p;5859len = principal->len;60p = (uint8_t *) principal->name;61while (len > 0) {62n = len;63if (n > 16)64n = 16;65for (i = 0; i < n; i++)66printf("%02x ", p[i]);67for (; i < 16; i++)68printf(" ");69printf("|");70for (i = 0; i < n; i++)71printf("%c", isprint(p[i]) ? p[i] : '.');72printf("|\n");73len -= n;74p += n;75}76}7778static void79test_client(int argc, const char **argv)80{81rpcproc_t prog = 123456;82rpcvers_t vers = 1;83const char *netid = "tcp";84char hostname[128], service[128+5];85CLIENT *client;86AUTH *auth;87const char **mechs;88rpc_gss_options_req_t options_req;89rpc_gss_options_ret_t options_ret;90rpc_gss_service_t svc;91struct timeval tv;92enum clnt_stat stat;9394if (argc == 2)95strlcpy(hostname, argv[1], sizeof(hostname));96else97gethostname(hostname, sizeof(hostname));9899client = clnt_create(hostname, prog, vers, netid);100if (!client) {101printf("rpc_createerr.cf_stat = %d\n",102rpc_createerr.cf_stat);103printf("rpc_createerr.cf_error.re_errno = %d\n",104rpc_createerr.cf_error.re_errno);105return;106}107108strcpy(service, "host");109strcat(service, "@");110strcat(service, hostname);111112mechs = rpc_gss_get_mechanisms();113auth = NULL;114while (*mechs) {115options_req.req_flags = GSS_C_MUTUAL_FLAG;116options_req.time_req = 600;117options_req.my_cred = GSS_C_NO_CREDENTIAL;118options_req.input_channel_bindings = NULL;119auth = rpc_gss_seccreate(client, service,120*mechs,121rpc_gss_svc_none,122NULL,123&options_req,124&options_ret);125if (auth)126break;127mechs++;128}129if (!auth) {130clnt_pcreateerror("rpc_gss_seccreate");131printf("Can't authenticate with server %s.\n",132hostname);133exit(1);134}135client->cl_auth = auth;136137for (svc = rpc_gss_svc_none; svc <= rpc_gss_svc_privacy; svc++) {138const char *svc_names[] = {139"rpc_gss_svc_default",140"rpc_gss_svc_none",141"rpc_gss_svc_integrity",142"rpc_gss_svc_privacy"143};144int num;145146rpc_gss_set_defaults(auth, svc, NULL);147tv.tv_sec = 5;148tv.tv_usec = 0;149num = 42;150stat = CLNT_CALL(client, 1,151(xdrproc_t) xdr_int, (char *) &num,152(xdrproc_t) xdr_int, (char *) &num, tv);153if (stat == RPC_SUCCESS) {154printf("succeeded with %s\n", svc_names[svc]);155if (num != 142)156printf("unexpected reply %d\n", num);157} else {158clnt_perror(client, "call failed");159}160}161AUTH_DESTROY(auth);162CLNT_DESTROY(client);163}164165static void166server_program_1(struct svc_req *rqstp, register SVCXPRT *transp)167{168rpc_gss_rawcred_t *rcred;169rpc_gss_ucred_t *ucred;170int i, num;171172if (rqstp->rq_cred.oa_flavor != RPCSEC_GSS) {173svcerr_weakauth(transp);174return;175}176177if (!rpc_gss_getcred(rqstp, &rcred, &ucred, NULL)) {178svcerr_systemerr(transp);179return;180}181182printf("svc=%d, mech=%s, uid=%d, gid=%d, gids={",183rcred->service, rcred->mechanism, ucred->uid, ucred->gid);184for (i = 0; i < ucred->gidlen; i++) {185if (i > 0) printf(",");186printf("%d", ucred->gidlist[i]);187}188printf("}\n");189190switch (rqstp->rq_proc) {191case 0:192if (!svc_getargs(transp, (xdrproc_t) xdr_void, 0)) {193svcerr_decode(transp);194goto out;195}196if (!svc_sendreply(transp, (xdrproc_t) xdr_void, 0)) {197svcerr_systemerr(transp);198}199goto out;200201case 1:202if (!svc_getargs(transp, (xdrproc_t) xdr_int,203(char *) &num)) {204svcerr_decode(transp);205goto out;206}207num += 100;208if (!svc_sendreply(transp, (xdrproc_t) xdr_int,209(char *) &num)) {210svcerr_systemerr(transp);211}212goto out;213214default:215svcerr_noproc(transp);216goto out;217}218219out:220return;221}222223#if 0224static void225report_error(gss_OID mech, OM_uint32 maj, OM_uint32 min)226{227OM_uint32 maj_stat, min_stat;228OM_uint32 message_context;229gss_buffer_desc buf;230231printf("major_stat=%d, minor_stat=%d\n", maj, min);232233message_context = 0;234do {235maj_stat = gss_display_status(&min_stat, maj,236GSS_C_GSS_CODE, GSS_C_NO_OID, &message_context, &buf);237printf("%.*s\n", (int)buf.length, (char *) buf.value);238gss_release_buffer(&min_stat, &buf);239} while (message_context);240if (mech) {241message_context = 0;242do {243maj_stat = gss_display_status(&min_stat, min,244GSS_C_MECH_CODE, mech, &message_context, &buf);245printf("%.*s\n", (int)buf.length, (char *) buf.value);246gss_release_buffer(&min_stat, &buf);247} while (message_context);248}249exit(1);250}251#endif252253static bool_t254server_new_context(__unused struct svc_req *req,255__unused gss_cred_id_t deleg,256__unused gss_ctx_id_t gss_context,257rpc_gss_lock_t *lock,258__unused void **cookie)259{260rpc_gss_rawcred_t *rcred = lock->raw_cred;261262printf("new security context version=%d, mech=%s, qop=%s:\n",263rcred->version, rcred->mechanism, rcred->qop);264print_principal(rcred->client_principal);265266if (!server_acl)267return (TRUE);268269if (rcred->client_principal->len != server_acl->len270|| memcmp(rcred->client_principal->name, server_acl->name,271server_acl->len)) {272return (FALSE);273}274275return (TRUE);276}277278static void279test_server(__unused int argc, __unused const char **argv)280{281char hostname[128];282char principal[128 + 5];283const char **mechs;284static rpc_gss_callback_t cb;285286if (argc == 3) {287if (!rpc_gss_get_principal_name(&server_acl, argv[1],288argv[2], NULL, NULL)) {289printf("Can't create %s ACL entry for %s\n",290argv[1], argv[2]);291return;292}293}294295gethostname(hostname, sizeof(hostname));;296snprintf(principal, sizeof(principal), "host@%s", hostname);297298mechs = rpc_gss_get_mechanisms();299while (*mechs) {300if (!rpc_gss_set_svc_name(principal, *mechs, GSS_C_INDEFINITE,301123456, 1)) {302rpc_gss_error_t e;303304rpc_gss_get_error(&e);305printf("setting name for %s for %s failed: %d, %d\n",306principal, *mechs,307e.rpc_gss_error, e.system_error);308309#if 0310gss_OID mech_oid;311gss_OID_set_desc oid_set;312gss_name_t name;313OM_uint32 maj_stat, min_stat;314gss_buffer_desc namebuf;315gss_cred_id_t cred;316317rpc_gss_mech_to_oid(*mechs, &mech_oid);318oid_set.count = 1;319oid_set.elements = mech_oid;320321namebuf.value = principal;322namebuf.length = strlen(principal);323maj_stat = gss_import_name(&min_stat, &namebuf,324GSS_C_NT_HOSTBASED_SERVICE, &name);325if (maj_stat) {326printf("gss_import_name failed\n");327report_error(mech_oid, maj_stat, min_stat);328}329maj_stat = gss_acquire_cred(&min_stat, name,3300, &oid_set, GSS_C_ACCEPT, &cred, NULL, NULL);331if (maj_stat) {332printf("gss_acquire_cred failed\n");333report_error(mech_oid, maj_stat, min_stat);334}335#endif336}337mechs++;338}339340cb.program = 123456;341cb.version = 1;342cb.callback = server_new_context;343rpc_gss_set_callback(&cb);344345svc_create(server_program_1, 123456, 1, 0);346svc_run();347}348349static void350test_get_principal_name(int argc, const char **argv)351{352const char *mechname, *name, *node, *domain;353rpc_gss_principal_t principal;354355if (argc < 3 || argc > 5) {356printf("usage: rpctest principal <mechname> <name> "357"[<node> [<domain>] ]\n");358exit(1);359}360361mechname = argv[1];362name = argv[2];363node = NULL;364domain = NULL;365if (argc > 3) {366node = argv[3];367if (argc > 4)368domain = argv[4];369}370371if (rpc_gss_get_principal_name(&principal, mechname, name,372node, domain)) {373printf("succeeded:\n");374print_principal(principal);375free(principal);376} else {377printf("failed\n");378}379}380381int382main(int argc, const char **argv)383{384385if (argc < 2)386usage();387if (!strcmp(argv[1], "client"))388test_client(argc - 1, argv + 1);389else if (!strcmp(argv[1], "server"))390test_server(argc - 1, argv + 1);391else if (!strcmp(argv[1], "principal"))392test_get_principal_name(argc - 1, argv + 1);393else394usage();395396return (0);397}398399400