nfs-ganesha 1.4
|
00001 /* 00002 Copyright (c) 2004-2006 The Regents of the University of Michigan. 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without 00006 modification, are permitted provided that the following conditions 00007 are met: 00008 00009 1. Redistributions of source code must retain the above copyright 00010 notice, this list of conditions and the following disclaimer. 00011 2. Redistributions in binary form must reproduce the above copyright 00012 notice, this list of conditions and the following disclaimer in the 00013 documentation and/or other materials provided with the distribution. 00014 3. Neither the name of the University nor the names of its 00015 contributors may be used to endorse or promote products derived 00016 from this software without specific prior written permission. 00017 00018 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 00019 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00021 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00022 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00023 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00024 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 00025 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00026 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00027 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 */ 00030 00031 #ifdef HAVE_CONFIG_H 00032 #include <config.h> 00033 #endif /* HAVE_CONFIG_H */ 00034 00035 #ifndef HAVE_LUCID_CONTEXT_SUPPORT 00036 #ifdef HAVE_KRB5 00037 00038 #include <stdio.h> 00039 #include <syslog.h> 00040 #include <string.h> 00041 #include <errno.h> 00042 #include <gssapi/gssapi.h> 00043 #include <rpc/rpc.h> 00044 #include <rpc/auth_gss.h> 00045 #include "gss_util.h" 00046 #include "gss_oids.h" 00047 #include "err_util.h" 00048 #include "context.h" 00049 00050 #include <krb5.h> 00051 00052 #if (KRB5_VERSION > 131) 00053 /* XXX argggg, there's gotta be a better way than just duplicating this 00054 * whole struct. Unfortunately, this is in a "private" header file, 00055 * so this is our best choice at this point :-/ 00056 */ 00057 00058 typedef struct _krb5_gss_ctx_id_rec { 00059 unsigned int initiate : 1; /* nonzero if initiating, zero if accepting */ 00060 unsigned int established : 1; 00061 unsigned int big_endian : 1; 00062 unsigned int have_acceptor_subkey : 1; 00063 unsigned int seed_init : 1; /* XXX tested but never actually set */ 00064 #ifdef CFX_EXERCISE 00065 unsigned int testing_unknown_tokid : 1; /* for testing only */ 00066 #endif 00067 OM_uint32 gss_flags; 00068 unsigned char seed[16]; 00069 krb5_principal here; 00070 krb5_principal there; 00071 krb5_keyblock *subkey; 00072 int signalg; 00073 size_t cksum_size; 00074 int sealalg; 00075 krb5_keyblock *enc; 00076 krb5_keyblock *seq; 00077 krb5_timestamp endtime; 00078 krb5_flags krb_flags; 00079 /* XXX these used to be signed. the old spec is inspecific, and 00080 the new spec specifies unsigned. I don't believe that the change 00081 affects the wire encoding. */ 00082 uint64_t seq_send; /* gssint_uint64 */ 00083 uint64_t seq_recv; /* gssint_uint64 */ 00084 void *seqstate; 00085 krb5_auth_context auth_context; 00086 gss_OID_desc *mech_used; /* gss_OID_desc */ 00087 /* Protocol spec revision 00088 0 => RFC 1964 with 3DES and RC4 enhancements 00089 1 => draft-ietf-krb-wg-gssapi-cfx-01 00090 No others defined so far. */ 00091 int proto; 00092 krb5_cksumtype cksumtype; /* for "main" subkey */ 00093 krb5_keyblock *acceptor_subkey; /* CFX only */ 00094 krb5_cksumtype acceptor_subkey_cksumtype; 00095 #ifdef CFX_EXERCISE 00096 gss_buffer_desc init_token; 00097 #endif 00098 } krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; 00099 00100 #else /* KRB5_VERSION > 131 */ 00101 00102 typedef struct _krb5_gss_ctx_id_rec { 00103 int initiate; 00104 u_int32_t gss_flags; 00105 int seed_init; 00106 unsigned char seed[16]; 00107 krb5_principal here; 00108 krb5_principal there; 00109 krb5_keyblock *subkey; 00110 int signalg; 00111 int cksum_size; 00112 int sealalg; 00113 krb5_keyblock *enc; 00114 krb5_keyblock *seq; 00115 krb5_timestamp endtime; 00116 krb5_flags krb_flags; 00117 krb5_ui_4 seq_send; 00118 krb5_ui_4 seq_recv; 00119 void *seqstate; 00120 int established; 00121 int big_endian; 00122 krb5_auth_context auth_context; 00123 gss_OID_desc *mech_used; 00124 int nctypes; 00125 krb5_cksumtype *ctypes; 00126 } krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; 00127 00128 #endif /* KRB5_VERSION */ 00129 00130 00131 static int 00132 write_keyblock(char **p, char *end, struct _krb5_keyblock *arg) 00133 { 00134 gss_buffer_desc tmp; 00135 00136 if (WRITE_BYTES(p, end, arg->enctype)) return -1; 00137 tmp.length = arg->length; 00138 tmp.value = arg->contents; 00139 if (write_buffer(p, end, &tmp)) return -1; 00140 return 0; 00141 } 00142 00143 /* 00144 * We really shouldn't know about glue-layer context structure, but 00145 * we need to get at the real krb5 context pointer. This should be 00146 * removed as soon as we say there is no support for MIT Kerberos 00147 * prior to 1.4 -- which gives us "legal" access to the context info. 00148 */ 00149 typedef struct gss_union_ctx_id_t { 00150 gss_OID mech_type; 00151 gss_ctx_id_t internal_ctx_id; 00152 } gss_union_ctx_id_desc, *gss_union_ctx_id_t; 00153 00154 int 00155 serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf, int32_t *endtime) 00156 { 00157 krb5_gss_ctx_id_t kctx = (krb5_gss_ctx_id_t) ((gss_union_ctx_id_t)ctx)->internal_ctx_id; 00158 char *p, *end; 00159 static int constant_zero = 0; 00160 static int constant_one = 1; 00161 static int constant_two __attribute__((unused)) = 2; 00162 uint32_t word_seq_send; 00163 u_int64_t seq_send_64bit; 00164 uint32_t v2_flags = 0; 00165 00166 if (!(buf->value = calloc(1, MAX_CTX_LEN))) 00167 goto out_err; 00168 p = buf->value; 00169 end = buf->value + MAX_CTX_LEN; 00170 00171 switch (kctx->enc->enctype) { 00172 case ENCTYPE_DES_CBC_CRC: 00173 case ENCTYPE_DES_CBC_MD4: 00174 case ENCTYPE_DES_CBC_MD5: 00175 case ENCTYPE_DES_CBC_RAW: 00176 /* Old format of context to the kernel */ 00177 if (kctx->initiate) { 00178 if (WRITE_BYTES(&p, end, constant_one)) goto out_err; 00179 } 00180 else { 00181 if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; 00182 } 00183 if (kctx->seed_init) { 00184 if (WRITE_BYTES(&p, end, constant_one)) goto out_err; 00185 } 00186 else { 00187 if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; 00188 } 00189 if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed))) 00190 goto out_err; 00191 if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err; 00192 if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err; 00193 if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; 00194 if (endtime) 00195 *endtime = kctx->endtime; 00196 word_seq_send = kctx->seq_send; 00197 if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err; 00198 if (write_oid(&p, end, kctx->mech_used)) goto out_err; 00199 00200 printerr(2, "serialize_krb5_ctx: serializing keys with " 00201 "enctype %d and length %d\n", 00202 kctx->enc->enctype, kctx->enc->length); 00203 00204 if (write_keyblock(&p, end, kctx->enc)) goto out_err; 00205 if (write_keyblock(&p, end, kctx->seq)) goto out_err; 00206 break; 00207 case ENCTYPE_DES3_CBC_RAW: 00208 case ENCTYPE_DES3_CBC_SHA1: 00209 case ENCTYPE_ARCFOUR_HMAC: 00210 case ENCTYPE_ARCFOUR_HMAC_EXP: 00211 case ENCTYPE_AES128_CTS_HMAC_SHA1_96: 00212 case ENCTYPE_AES256_CTS_HMAC_SHA1_96: 00213 /* New format of context to the kernel */ 00214 /* u32 flags; 00215 * #define KRB5_CTX_FLAG_INITIATOR 0x00000001 00216 * #define KRB5_CTX_FLAG_CFX 0x00000002 00217 * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 00218 * s32 endtime; 00219 * u64 seq_send; 00220 * u32 enctype; 00221 * rawkey data 00222 */ 00223 00224 if (kctx->initiate) 00225 v2_flags |= KRB5_CTX_FLAG_INITIATOR; 00226 if (kctx->proto == 1) 00227 v2_flags |= KRB5_CTX_FLAG_CFX; 00228 if (kctx->have_acceptor_subkey) 00229 v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY; 00230 if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; 00231 if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; 00232 00233 seq_send_64bit = kctx->seq_send; 00234 if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err; 00235 00236 if (kctx->have_acceptor_subkey) { 00237 if (WRITE_BYTES(&p, end, kctx->acceptor_subkey->enctype)) 00238 goto out_err; 00239 printerr(2, "serialize_krb5_ctx: serializing subkey " 00240 "with enctype %d and size %d\n", 00241 kctx->acceptor_subkey->enctype, 00242 kctx->acceptor_subkey->length); 00243 00244 if (write_bytes(&p, end, 00245 kctx->acceptor_subkey->contents, 00246 kctx->acceptor_subkey->length)) 00247 goto out_err; 00248 } else { 00249 if (WRITE_BYTES(&p, end, kctx->enc->enctype)) 00250 goto out_err; 00251 printerr(2, "serialize_krb5_ctx: serializing key " 00252 "with enctype %d and size %d\n", 00253 kctx->enc->enctype, kctx->enc->length); 00254 00255 if (write_bytes(&p, end, kctx->enc->contents, 00256 kctx->enc->length)) 00257 goto out_err; 00258 } 00259 break; 00260 default: 00261 printerr(0, "ERROR: serialize_krb5_ctx: unsupported encryption " 00262 "algorithm %d\n", kctx->enc->enctype); 00263 goto out_err; 00264 } 00265 00266 buf->length = p - (char *)buf->value; 00267 return 0; 00268 00269 out_err: 00270 printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); 00271 if (buf->value) { 00272 free(buf->value); 00273 } 00274 buf->value = NULL; 00275 buf->length = 0; 00276 return -1; 00277 } 00278 00279 #endif /* HAVE_KRB5 */ 00280 #endif /* HAVE_LUCID_CONTEXT_SUPPORT */