nfs-ganesha 1.4

gss_util.c

Go to the documentation of this file.
00001 /*
00002  *  Adapted in part from MIT Kerberos 5-1.2.1 slave/kprop.c and from
00003  *  http://docs.sun.com/?p=/doc/816-1331/6m7oo9sms&a=view
00004  *
00005  *  Copyright (c) 2002 The Regents of the University of Michigan.
00006  *  All rights reserved.
00007  *
00008  *  Andy Adamson <andros@umich.edu>
00009  *  J. Bruce Fields <bfields@umich.edu>
00010  *  Marius Aamodt Eriksen <marius@umich.edu>
00011  */
00012 
00013 /*
00014  * slave/kprop.c
00015  *
00016  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
00017  * All Rights Reserved.
00018  *
00019  * Export of this software from the United States of America may
00020  *   require a specific license from the United States Government.
00021  *   It is the responsibility of any person or organization contemplating
00022  *   export to obtain such a license before exporting.
00023  *
00024  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
00025  * distribute this software and its documentation for any purpose and
00026  * without fee is hereby granted, provided that the above copyright
00027  * notice appear in all copies and that both that copyright notice and
00028  * this permission notice appear in supporting documentation, and that
00029  * the name of M.I.T. not be used in advertising or publicity pertaining
00030  * to distribution of the software without specific, written prior
00031  * permission.  Furthermore if you modify this software you must label
00032  * your software as modified software and not distribute it in such a
00033  * fashion that it might be confused with the original M.I.T. software.
00034  * M.I.T. makes no representations about the suitability of
00035  * this software for any purpose.  It is provided "as is" without express
00036  * or implied warranty.
00037  */
00038 
00039 /*
00040  * Copyright 1994 by OpenVision Technologies, Inc.
00041  *
00042  * Permission to use, copy, modify, distribute, and sell this software
00043  * and its documentation for any purpose is hereby granted without fee,
00044  * provided that the above copyright notice appears in all copies and
00045  * that both that copyright notice and this permission notice appear in
00046  * supporting documentation, and that the name of OpenVision not be used
00047  * in advertising or publicity pertaining to distribution of the software
00048  * without specific, written prior permission. OpenVision makes no
00049  * representations about the suitability of this software for any
00050  * purpose.  It is provided "as is" without express or implied warranty.
00051  *
00052  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
00053  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
00054  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
00055  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
00056  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
00057  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00058  * PERFORMANCE OF THIS SOFTWARE.
00059  */
00060 
00061 #ifdef HAVE_CONFIG_H
00062 #include <config.h>
00063 #endif  /* HAVE_CONFIG_H */
00064 
00065 #include <errno.h>
00066 #include <stdio.h>
00067 #include <ctype.h>
00068 #include <sys/file.h>
00069 #include <signal.h>
00070 #include <string.h>
00071 #include <sys/types.h>
00072 #include <sys/time.h>
00073 #include <sys/stat.h>
00074 #include <sys/socket.h>
00075 #include <netinet/in.h>
00076 #include <sys/param.h>
00077 #include <netdb.h>
00078 #include <fcntl.h>
00079 #include <gssapi/gssapi.h>
00080 #if defined(HAVE_KRB5) && !defined(GSS_C_NT_HOSTBASED_SERVICE)
00081 #include <gssapi/gssapi_generic.h>
00082 #define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
00083 #endif
00084 #include "gss_util.h"
00085 #include "err_util.h"
00086 #include "gssd.h"
00087 #ifdef HAVE_UNISTD_H
00088 #include <unistd.h>
00089 #endif
00090 #include <stdlib.h>
00091 #ifdef HAVE_COM_ERR_H
00092 #include <com_err.h>
00093 #endif
00094 
00095 /* Global gssd_credentials handle */
00096 gss_cred_id_t gssd_creds;
00097 
00098 gss_OID g_mechOid = GSS_C_NULL_OID;;
00099 
00100 #if 0
00101 static void
00102 display_status_1(char *m, u_int32_t code, int type, const gss_OID mech)
00103 {
00104         u_int32_t maj_stat, min_stat;
00105         gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
00106         u_int32_t msg_ctx = 0;
00107         char *typestr;
00108 
00109         switch (type) {
00110         case GSS_C_GSS_CODE:
00111                 typestr = "GSS";
00112                 break;
00113         case GSS_C_MECH_CODE:
00114                 typestr = "mechanism";
00115                 break;
00116         default:
00117                 return;
00118                 /* NOTREACHED */
00119         }
00120 
00121         for (;;) {
00122                 maj_stat = gss_display_status(&min_stat, code,
00123                     type, mech, &msg_ctx, &msg);
00124                 if (maj_stat != GSS_S_COMPLETE) {
00125                         printerr(0, "ERROR: in call to "
00126                                 "gss_display_status called from %s\n", m);
00127                         break;
00128                 } else {
00129                         printerr(0, "ERROR: GSS-API: (%s) error in %s(): %s\n",
00130                             typestr, m, (char *)msg.value);
00131                 }
00132 
00133                 if (msg.length != 0)
00134                         (void) gss_release_buffer(&min_stat, &msg);
00135 
00136                 if (msg_ctx == 0)
00137                         break;
00138         }
00139 }
00140 #endif
00141 static char *
00142 gss_display_error(OM_uint32 status)
00143 {
00144                 char *error = NULL;
00145 
00146                 switch(status) {
00147                 case GSS_S_COMPLETE: 
00148                         error = "GSS_S_COMPLETE";
00149                         break;
00150                 case GSS_S_CALL_INACCESSIBLE_READ: 
00151                         error = "GSS_S_CALL_INACCESSIBLE_READ";
00152                         break;
00153                 case GSS_S_CALL_INACCESSIBLE_WRITE:
00154                         error = "GSS_S_CALL_INACCESSIBLE_WRITE";
00155                         break;
00156                 case GSS_S_CALL_BAD_STRUCTURE:
00157                         error = "GSS_S_CALL_BAD_STRUCTURE";
00158                         break;
00159                 case  GSS_S_BAD_MECH:
00160                         error = "GSS_S_BAD_MECH";
00161                         break;
00162                 case  GSS_S_BAD_NAME:
00163                         error = "GSS_S_BAD_NAME";
00164                         break;
00165                 case  GSS_S_BAD_NAMETYPE:
00166                         error = "GSS_S_BAD_NAMETYPE";
00167                         break;
00168                 case  GSS_S_BAD_BINDINGS:
00169                         error = "GSS_S_BAD_BINDINGS";
00170                         break;
00171                 case  GSS_S_BAD_STATUS:
00172                         error = "GSS_S_BAD_STATUS";
00173                         break;
00174                 case  GSS_S_BAD_SIG:
00175                         error = "GSS_S_BAD_SIG";
00176                         break;
00177                 case  GSS_S_NO_CRED:
00178                         error = "GSS_S_NO_CRED";
00179                         break;
00180                 case  GSS_S_NO_CONTEXT:
00181                         error = "GSS_S_NO_CONTEXT";
00182                         break;
00183                 case  GSS_S_DEFECTIVE_TOKEN:
00184                         error = "GSS_S_DEFECTIVE_TOKEN";
00185                         break;
00186                 case  GSS_S_DEFECTIVE_CREDENTIAL:
00187                         error = "GSS_S_DEFECTIVE_CREDENTIAL";
00188                         break;
00189                 case  GSS_S_CREDENTIALS_EXPIRED:
00190                         error = "GSS_S_CREDENTIALS_EXPIRED";
00191                         break;
00192                 case  GSS_S_CONTEXT_EXPIRED:
00193                         error = "GSS_S_CONTEXT_EXPIRED";
00194                         break;
00195                 case  GSS_S_FAILURE:
00196                         error = "GSS_S_FAILURE";
00197                         break;
00198                 case  GSS_S_BAD_QOP:
00199                         error = "GSS_S_BAD_QOP";
00200                         break;
00201                 case  GSS_S_UNAUTHORIZED:
00202                         error = "GSS_S_UNAUTHORIZED";
00203                         break;
00204                 case  GSS_S_UNAVAILABLE:
00205                         error = "GSS_S_UNAVAILABLE";
00206                         break;
00207                 case  GSS_S_DUPLICATE_ELEMENT:
00208                         error = "GSS_S_DUPLICATE_ELEMENT";
00209                         break;
00210                 case  GSS_S_NAME_NOT_MN:
00211                         error = "GSS_S_NAME_NOT_MN";
00212                         break;
00213                 default:
00214                         error = "Not defined";
00215                 }
00216         return error;
00217 }
00218 
00219 static void
00220 display_status_2(char *m, u_int32_t major, u_int32_t minor, const gss_OID mech)
00221 {
00222         u_int32_t maj_stat1, min_stat1;
00223         u_int32_t maj_stat2, min_stat2;
00224         gss_buffer_desc maj_gss_buf = GSS_C_EMPTY_BUFFER;
00225         gss_buffer_desc min_gss_buf = GSS_C_EMPTY_BUFFER;
00226         char maj_buf[30], min_buf[30];
00227         char *maj, *min;
00228         u_int32_t msg_ctx = 0;
00229         int msg_verbosity __attribute__((unused)) = 0;
00230 
00231         /* Get major status message */
00232         maj_stat1 = gss_display_status(&min_stat1, major,
00233                 GSS_C_GSS_CODE, mech, &msg_ctx, &maj_gss_buf);
00234 
00235         if (maj_stat1 != GSS_S_COMPLETE) {
00236                 snprintf(maj_buf, sizeof(maj_buf), "(0x%08x)", major);
00237                 maj = &maj_buf[0];
00238         } else {
00239                 maj = maj_gss_buf.value;
00240         }
00241 
00242         /* Get minor status message */
00243         maj_stat2 = gss_display_status(&min_stat2, minor,
00244                 GSS_C_MECH_CODE, mech, &msg_ctx, &min_gss_buf);
00245 
00246         if (maj_stat2 != GSS_S_COMPLETE) {
00247                 snprintf(min_buf, sizeof(min_buf), "(0x%08x)", minor);
00248                 min = &min_buf[0];
00249         } else {
00250                 min = min_gss_buf.value;
00251         }
00252 
00253         if (major == GSS_S_CREDENTIALS_EXPIRED)
00254                 msg_verbosity = 1;
00255 
00256         printerr(msg_verbosity, "ERROR: GSS-API: error in %s(): %s (%s) - %s\n",
00257                  m, gss_display_error(major), maj, min);
00258 
00259         if (maj_gss_buf.length != 0)
00260                 (void) gss_release_buffer(&min_stat1, &maj_gss_buf);
00261         if (min_gss_buf.length != 0)
00262                 (void) gss_release_buffer(&min_stat2, &min_gss_buf);
00263 }
00264 
00265 void
00266 pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat, const gss_OID mech)
00267 {
00268         display_status_2(msg, maj_stat, min_stat, mech);
00269 }
00270 
00271 int
00272 gssd_acquire_cred(char *server_name, const gss_OID oid)
00273 {
00274         gss_buffer_desc name;
00275         gss_name_t target_name;
00276         u_int32_t maj_stat, min_stat;
00277         u_int32_t ignore_maj_stat, ignore_min_stat;
00278         gss_buffer_desc pbuf;
00279 
00280         /* If server_name is NULL, get cred for GSS_C_NO_NAME */
00281         if (server_name == NULL) {
00282                 target_name = GSS_C_NO_NAME;
00283         } else {
00284                 name.value = (void *)server_name;
00285                 name.length = strlen(server_name);
00286 
00287                 maj_stat = gss_import_name(&min_stat, &name,
00288                                 oid,
00289                                 &target_name);
00290 
00291                 if (maj_stat != GSS_S_COMPLETE) {
00292                         pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid);
00293                         return (FALSE);
00294                 }
00295         }
00296 
00297         maj_stat = gss_acquire_cred(&min_stat, target_name, GSS_C_INDEFINITE,
00298                         GSS_C_NO_OID_SET, GSS_C_ACCEPT,
00299                         &gssd_creds, NULL, NULL);
00300 
00301         if (maj_stat != GSS_S_COMPLETE) {
00302                 pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid);
00303                 ignore_maj_stat = gss_display_name(&ignore_min_stat,
00304                                 target_name, &pbuf, NULL);
00305                 if (ignore_maj_stat == GSS_S_COMPLETE) {
00306                         printerr(1, "Unable to obtain credentials for '%.*s'\n",
00307                                  pbuf.length, pbuf.value);
00308                         ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
00309                                                              &pbuf);
00310                 }
00311         }
00312 
00313         ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);
00314 
00315         return (maj_stat == GSS_S_COMPLETE);
00316 }
00317 
00318 int gssd_check_mechs(void)
00319 {
00320         u_int32_t maj_stat, min_stat;
00321         gss_OID_set supported_mechs = GSS_C_NO_OID_SET;
00322         int retval = -1;
00323 
00324         maj_stat = gss_indicate_mechs(&min_stat, &supported_mechs);
00325         if (maj_stat != GSS_S_COMPLETE) {
00326                 printerr(0, "Unable to obtain list of supported mechanisms. "
00327                          "Check that gss library is properly configured.\n");
00328                 goto out;
00329         }
00330         if (supported_mechs == GSS_C_NO_OID_SET ||
00331             supported_mechs->count == 0) {
00332                 printerr(0, "Unable to obtain list of supported mechanisms. "
00333                          "Check that gss library is properly configured.\n");
00334                 goto out;
00335         }
00336         maj_stat = gss_release_oid_set(&min_stat, &supported_mechs);
00337         retval = 0;
00338 out:
00339         return retval;
00340 }
00341