gss-serv-krb5.c revision 128456
135137Sphk/* $OpenBSD: gss-serv-krb5.c,v 1.2 2003/11/21 11:57:03 djm Exp $ */ 235137Sphk 335137Sphk/* 435137Sphk * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. 535137Sphk * 635137Sphk * Redistribution and use in source and binary forms, with or without 735137Sphk * modification, are permitted provided that the following conditions 835137Sphk * are met: 935137Sphk * 1. Redistributions of source code must retain the above copyright 1035137Sphk * notice, this list of conditions and the following disclaimer. 1135137Sphk * 2. Redistributions in binary form must reproduce the above copyright 1235137Sphk * notice, this list of conditions and the following disclaimer in the 1335137Sphk * documentation and/or other materials provided with the distribution. 1435137Sphk * 1535137Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 1635137Sphk * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1735137Sphk * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1835137Sphk * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1935137Sphk * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2035137Sphk * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2135137Sphk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2235137Sphk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2335137Sphk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2435137Sphk * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2535137Sphk */ 2635137Sphk 2735137Sphk#include "includes.h" 2835137Sphk 2935137Sphk#ifdef GSSAPI 3061438Sasmodai#ifdef KRB5 3135137Sphk 3235137Sphk#include "auth.h" 3335137Sphk#include "xmalloc.h" 3435137Sphk#include "log.h" 3535137Sphk#include "servconf.h" 3635137Sphk 3761438Sasmodai#include "ssh-gss.h" 3861438Sasmodai 3935137Sphkextern ServerOptions options; 4035137Sphk 4135137Sphk#ifdef HEIMDAL 4235137Sphk# include <krb5.h> 4361438Sasmodai#else 4435137Sphk# ifdef HAVE_GSSAPI_KRB5 4535137Sphk# include <gssapi_krb5.h> 4635137Sphk# elif HAVE_GSSAPI_GSSAPI_KRB5 4735137Sphk# include <gssapi/gssapi_krb5.h> 4835137Sphk# endif 4935137Sphk#endif 5035137Sphk 5145114Sphkstatic krb5_context krb_context = NULL; 5245114Sphk 5345114Sphk/* Initialise the krb5 library, for the stuff that GSSAPI won't do */ 5445114Sphk 5545114Sphkstatic int 5645114Sphkssh_gssapi_krb5_init() 5745114Sphk{ 5837669Scharnier krb5_error_code problem; 5937669Scharnier 6050476Speter if (krb_context != NULL) 6137669Scharnier return 1; 6235137Sphk 6335734Scharnier problem = krb5_init_context(&krb_context); 6435734Scharnier if (problem) { 6535137Sphk logit("Cannot initialize krb5 context"); 6635137Sphk return 0; 6735137Sphk } 6835137Sphk#ifdef KRB5_INIT_ETS 6935734Scharnier krb5_init_ets(krb_context); 7035137Sphk#endif 7135137Sphk 7235137Sphk return 1; 7335137Sphk} 7435137Sphk 7535137Sphk/* Check if this user is OK to login. This only works with krb5 - other 7635137Sphk * GSSAPI mechanisms will need their own. 7735734Scharnier * Returns true if the user is OK to log in, otherwise returns 0 7835137Sphk */ 7935137Sphk 8035137Sphkstatic int 8135137Sphkssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) 8235137Sphk{ 8335137Sphk krb5_principal princ; 8435137Sphk int retval; 8535137Sphk 8635137Sphk if (ssh_gssapi_krb5_init() == 0) 8735734Scharnier return 0; 8835734Scharnier 8935137Sphk if ((retval = krb5_parse_name(krb_context, client->exportedname.value, 9035137Sphk &princ))) { 9135137Sphk logit("krb5_parse_name(): %.100s", 9235137Sphk krb5_get_err_text(krb_context, retval)); 9335137Sphk return 0; 9435137Sphk } 9535137Sphk if (krb5_kuserok(krb_context, princ, name)) { 9635137Sphk retval = 1; 9735137Sphk logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", 9837669Scharnier name, (char *)client->displayname.value); 9935137Sphk } else 10035137Sphk retval = 0; 10135137Sphk 10235137Sphk krb5_free_principal(krb_context, princ); 10335137Sphk return retval; 10435137Sphk} 10535137Sphk 10635137Sphk 10735137Sphk/* This writes out any forwarded credentials from the structure populated 10835137Sphk * during userauth. Called after we have setuid to the user */ 10935137Sphk 11035137Sphkstatic void 11135137Sphkssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 11235137Sphk{ 11335137Sphk krb5_ccache ccache; 11435137Sphk krb5_error_code problem; 11537669Scharnier krb5_principal princ; 11635137Sphk OM_uint32 maj_status, min_status; 11735137Sphk int len; 11835137Sphk 11935137Sphk if (client->creds == NULL) { 12035137Sphk debug("No credentials stored"); 12135137Sphk return; 12235137Sphk } 12335137Sphk 12435137Sphk if (ssh_gssapi_krb5_init() == 0) 12535137Sphk return; 12635137Sphk 12735137Sphk#ifdef HEIMDAL 12835137Sphk if ((problem = krb5_cc_gen_new(krb_context, &krb5_fcc_ops, &ccache))) { 12935137Sphk logit("krb5_cc_gen_new(): %.100s", 13038023Sbde krb5_get_err_text(krb_context, problem)); 13135137Sphk return; 13235137Sphk } 13335137Sphk#else 13435137Sphk { 13535137Sphk int tmpfd; 13635137Sphk char ccname[40]; 13735137Sphk 13835137Sphk snprintf(ccname, sizeof(ccname), 13935137Sphk "FILE:/tmp/krb5cc_%d_XXXXXX", geteuid()); 14035137Sphk 14135137Sphk if ((tmpfd = mkstemp(ccname + strlen("FILE:"))) == -1) { 14235137Sphk logit("mkstemp(): %.100s", strerror(errno)); 14335137Sphk problem = errno; 14435137Sphk return; 14535137Sphk } 14635137Sphk if (fchmod(tmpfd, S_IRUSR | S_IWUSR) == -1) { 14735137Sphk logit("fchmod(): %.100s", strerror(errno)); 14835137Sphk close(tmpfd); 14935137Sphk problem = errno; 15035137Sphk return; 15135137Sphk } 15235137Sphk close(tmpfd); 15335137Sphk if ((problem = krb5_cc_resolve(krb_context, ccname, &ccache))) { 15435137Sphk logit("krb5_cc_resolve(): %.100s", 15535137Sphk krb5_get_err_text(krb_context, problem)); 15635137Sphk return; 15735137Sphk } 15837669Scharnier } 15935137Sphk#endif /* #ifdef HEIMDAL */ 16035137Sphk 16135137Sphk if ((problem = krb5_parse_name(krb_context, 16235137Sphk client->exportedname.value, &princ))) { 16335137Sphk logit("krb5_parse_name(): %.100s", 16437669Scharnier krb5_get_err_text(krb_context, problem)); 16535137Sphk krb5_cc_destroy(krb_context, ccache); 16635137Sphk return; 16735137Sphk } 16835137Sphk 16935137Sphk if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) { 17035137Sphk logit("krb5_cc_initialize(): %.100s", 17135137Sphk krb5_get_err_text(krb_context, problem)); 17237669Scharnier krb5_free_principal(krb_context, princ); 17335137Sphk krb5_cc_destroy(krb_context, ccache); 17435137Sphk return; 17535137Sphk } 17635137Sphk 17735137Sphk krb5_free_principal(krb_context, princ); 17835137Sphk 17935137Sphk if ((maj_status = gss_krb5_copy_ccache(&min_status, 18035137Sphk client->creds, ccache))) { 18137669Scharnier logit("gss_krb5_copy_ccache() failed"); 18235137Sphk krb5_cc_destroy(krb_context, ccache); 18335137Sphk return; 18435137Sphk } 18535137Sphk 18635137Sphk client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); 18735137Sphk client->store.envvar = "KRB5CCNAME"; 18835137Sphk len = strlen(client->store.filename) + 6; 18935137Sphk client->store.envval = xmalloc(len); 19035137Sphk snprintf(client->store.envval, len, "FILE:%s", client->store.filename); 19135137Sphk 19235137Sphk#ifdef USE_PAM 19337669Scharnier if (options.use_pam) 19435137Sphk do_pam_putenv(client->store.envvar, client->store.envval); 19535137Sphk#endif 19635137Sphk 19735137Sphk krb5_cc_close(krb_context, ccache); 19835137Sphk 19937669Scharnier return; 20035137Sphk} 20135137Sphk 20235137Sphkssh_gssapi_mech gssapi_kerberos_mech = { 20335137Sphk "toWM5Slw5Ew8Mqkay+al2g==", 20435137Sphk "Kerberos", 20535137Sphk {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, 20635137Sphk NULL, 20737669Scharnier &ssh_gssapi_krb5_userok, 20835137Sphk NULL, 20935137Sphk &ssh_gssapi_krb5_storecreds 21035137Sphk}; 21135137Sphk 21235137Sphk#endif /* KRB5 */ 21337669Scharnier 21435137Sphk#endif /* GSSAPI */ 21535137Sphk