15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
35 */
36
37 /*
38 * Kerberos V Security Support Provider
39 *
40 * Based on code previously in ctx.c (from Boris Popov?)
41 * but then mostly rewritten at Sun.
42 */
43
44 #include <errno.h>
45 #include <stdio.h>
46 #include <stddef.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <strings.h>
50 #include <netdb.h>
51 #include <libintl.h>
52 #include <xti.h>
53 #include <assert.h>
54
251 {
252 int err;
253 struct smb_ctx *ctx = sp->smb_ctx;
254 krb5ssp_state_t *ss = sp->sp_private;
255 uchar_t *tkt = NULL;
256 ulong_t tktlen;
257 uchar_t *gtok = NULL; /* gssapi token */
258 ulong_t gtoklen; /* gssapi token length */
259 char *prin = ctx->ct_srvname;
260
261 if ((err = krb5ssp_get_tkt(ss, prin, &tkt, &tktlen)) != 0)
262 goto out;
263 if ((err = krb5ssp_tkt2gtok(tkt, tktlen, >ok, >oklen)) != 0)
264 goto out;
265
266 if ((err = mb_init_sz(out_mb, gtoklen)) != 0)
267 goto out;
268 if ((err = mb_put_mem(out_mb, gtok, gtoklen, MB_MSYSTEM)) != 0)
269 goto out;
270
271 if (ctx->ct_vcflags & SMBV_WILL_SIGN)
272 ctx->ct_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
273
274 out:
275 if (gtok)
276 free(gtok);
277 if (tkt)
278 free(tkt);
279
280 return (err);
281 }
282
283 /*
284 * Unwrap a GSS-API encapsulated RFC 1964 reply message,
285 * i.e. type KRB_AP_REP or KRB_ERROR.
286 */
287 int
288 krb5ssp_get_reply(struct ssp_ctx *sp, struct mbdata *in_mb)
289 {
290 krb5ssp_state_t *ss = sp->sp_private;
291 mbuf_t *m = in_mb->mb_top;
292 int err = EBADRPC;
293 int dlen, rc;
366 if (reply != NULL)
367 krb5_free_ap_rep_enc_part(ss->ss_krb5ctx, reply);
368 if (err)
369 DPRINT("ret %d", err);
370
371 return (err);
372 }
373
374 /*
375 * krb5ssp_final
376 *
377 * Called after successful authentication.
378 * Setup the MAC key for signing.
379 */
380 int
381 krb5ssp_final(struct ssp_ctx *sp)
382 {
383 struct smb_ctx *ctx = sp->smb_ctx;
384 krb5ssp_state_t *ss = sp->sp_private;
385 krb5_keyblock *ssn_key = NULL;
386 int err, len;
387
388 /*
389 * Save the session key, used for SMB signing
390 * and possibly other consumers (RPC).
391 */
392 err = krb5_auth_con_getlocalsubkey(
393 ss->ss_krb5ctx, ss->ss_auth, &ssn_key);
394 if (err != 0) {
395 DPRINT("_getlocalsubkey, err=0x%x (%s)",
396 err, error_message(err));
397 if (err <= 0 || err > ESTALE)
398 err = EAUTH;
399 goto out;
400 }
401 memset(ctx->ct_ssn_key, 0, SMBIOC_HASH_SZ);
402 if ((len = ssn_key->length) > SMBIOC_HASH_SZ)
403 len = SMBIOC_HASH_SZ;
404 memcpy(ctx->ct_ssn_key, ssn_key->contents, len);
405
406 /*
407 * Set the MAC key on the first successful auth.
408 */
409 if ((ctx->ct_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) &&
410 (ctx->ct_mackey == NULL)) {
411 ctx->ct_mackeylen = ssn_key->length;
412 ctx->ct_mackey = malloc(ctx->ct_mackeylen);
413 if (ctx->ct_mackey == NULL) {
414 ctx->ct_mackeylen = 0;
415 err = ENOMEM;
416 goto out;
417 }
418 memcpy(ctx->ct_mackey, ssn_key->contents,
419 ctx->ct_mackeylen);
420 /*
421 * Apparently, the server used seq. no. zero
422 * for our previous message, so next is two.
423 */
424 ctx->ct_mac_seqno = 2;
425 }
426 err = 0;
427
428 out:
429 if (ssn_key)
430 krb5_free_keyblock(ss->ss_krb5ctx, ssn_key);
431
432 return (err);
433 }
434
435 /*
436 * krb5ssp_next_token
437 *
438 * See ssp.c: ssp_ctx_next_token
439 */
440 int
441 krb5ssp_next_token(struct ssp_ctx *sp, struct mbdata *in_mb,
442 struct mbdata *out_mb)
443 {
444 int err;
445
446 /*
447 * Note: in_mb == NULL on the first call.
448 */
449 if (in_mb) {
|
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
35 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
36 */
37
38 /*
39 * Kerberos V Security Support Provider
40 *
41 * Based on code previously in ctx.c (from Boris Popov?)
42 * but then mostly rewritten at Sun.
43 */
44
45 #include <errno.h>
46 #include <stdio.h>
47 #include <stddef.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include <strings.h>
51 #include <netdb.h>
52 #include <libintl.h>
53 #include <xti.h>
54 #include <assert.h>
55
252 {
253 int err;
254 struct smb_ctx *ctx = sp->smb_ctx;
255 krb5ssp_state_t *ss = sp->sp_private;
256 uchar_t *tkt = NULL;
257 ulong_t tktlen;
258 uchar_t *gtok = NULL; /* gssapi token */
259 ulong_t gtoklen; /* gssapi token length */
260 char *prin = ctx->ct_srvname;
261
262 if ((err = krb5ssp_get_tkt(ss, prin, &tkt, &tktlen)) != 0)
263 goto out;
264 if ((err = krb5ssp_tkt2gtok(tkt, tktlen, >ok, >oklen)) != 0)
265 goto out;
266
267 if ((err = mb_init_sz(out_mb, gtoklen)) != 0)
268 goto out;
269 if ((err = mb_put_mem(out_mb, gtok, gtoklen, MB_MSYSTEM)) != 0)
270 goto out;
271
272 out:
273 if (gtok)
274 free(gtok);
275 if (tkt)
276 free(tkt);
277
278 return (err);
279 }
280
281 /*
282 * Unwrap a GSS-API encapsulated RFC 1964 reply message,
283 * i.e. type KRB_AP_REP or KRB_ERROR.
284 */
285 int
286 krb5ssp_get_reply(struct ssp_ctx *sp, struct mbdata *in_mb)
287 {
288 krb5ssp_state_t *ss = sp->sp_private;
289 mbuf_t *m = in_mb->mb_top;
290 int err = EBADRPC;
291 int dlen, rc;
364 if (reply != NULL)
365 krb5_free_ap_rep_enc_part(ss->ss_krb5ctx, reply);
366 if (err)
367 DPRINT("ret %d", err);
368
369 return (err);
370 }
371
372 /*
373 * krb5ssp_final
374 *
375 * Called after successful authentication.
376 * Setup the MAC key for signing.
377 */
378 int
379 krb5ssp_final(struct ssp_ctx *sp)
380 {
381 struct smb_ctx *ctx = sp->smb_ctx;
382 krb5ssp_state_t *ss = sp->sp_private;
383 krb5_keyblock *ssn_key = NULL;
384 int err;
385
386 /*
387 * Save the session key, used for SMB signing
388 * and possibly other consumers (RPC).
389 */
390 err = krb5_auth_con_getlocalsubkey(
391 ss->ss_krb5ctx, ss->ss_auth, &ssn_key);
392 if (err != 0) {
393 DPRINT("_getlocalsubkey, err=0x%x (%s)",
394 err, error_message(err));
395 if (err <= 0 || err > ESTALE)
396 err = EAUTH;
397 goto out;
398 }
399
400 /* Sanity check the length */
401 if (ssn_key->length > 1024) {
402 DPRINT("session key too long");
403 err = EAUTH;
404 goto out;
405 }
406
407 /*
408 * Update/save the session key.
409 */
410 if (ctx->ct_ssnkey_buf != NULL) {
411 free(ctx->ct_ssnkey_buf);
412 ctx->ct_ssnkey_buf = NULL;
413 }
414 ctx->ct_ssnkey_buf = malloc(ssn_key->length);
415 if (ctx->ct_ssnkey_buf == NULL) {
416 err = ENOMEM;
417 goto out;
418 }
419 ctx->ct_ssnkey_len = ssn_key->length;
420 memcpy(ctx->ct_ssnkey_buf, ssn_key->contents, ctx->ct_ssnkey_len);
421 err = 0;
422
423 out:
424 if (ssn_key != NULL)
425 krb5_free_keyblock(ss->ss_krb5ctx, ssn_key);
426
427 return (err);
428 }
429
430 /*
431 * krb5ssp_next_token
432 *
433 * See ssp.c: ssp_ctx_next_token
434 */
435 int
436 krb5ssp_next_token(struct ssp_ctx *sp, struct mbdata *in_mb,
437 struct mbdata *out_mb)
438 {
439 int err;
440
441 /*
442 * Note: in_mb == NULL on the first call.
443 */
444 if (in_mb) {
|