gss-serv-krb5.c revision 137015
1137015Sdes/* $OpenBSD: gss-serv-krb5.c,v 1.3 2004/07/21 10:36:23 djm Exp $ */ 2124208Sdes 3124208Sdes/* 4124208Sdes * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. 5124208Sdes * 6124208Sdes * Redistribution and use in source and binary forms, with or without 7124208Sdes * modification, are permitted provided that the following conditions 8124208Sdes * are met: 9124208Sdes * 1. Redistributions of source code must retain the above copyright 10124208Sdes * notice, this list of conditions and the following disclaimer. 11124208Sdes * 2. Redistributions in binary form must reproduce the above copyright 12124208Sdes * notice, this list of conditions and the following disclaimer in the 13124208Sdes * documentation and/or other materials provided with the distribution. 14124208Sdes * 15124208Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 16124208Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17124208Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18124208Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19124208Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20124208Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21124208Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22124208Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23124208Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24124208Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25124208Sdes */ 26124208Sdes 27124208Sdes#include "includes.h" 28124208Sdes 29124208Sdes#ifdef GSSAPI 30124208Sdes#ifdef KRB5 31124208Sdes 32124208Sdes#include "auth.h" 33124208Sdes#include "xmalloc.h" 34124208Sdes#include "log.h" 35124208Sdes#include "servconf.h" 36124208Sdes 37124208Sdes#include "ssh-gss.h" 38124208Sdes 39124208Sdesextern ServerOptions options; 40124208Sdes 41124208Sdes#ifdef HEIMDAL 42126274Sdes# include <krb5.h> 43124208Sdes#else 44126274Sdes# ifdef HAVE_GSSAPI_KRB5 45126274Sdes# include <gssapi_krb5.h> 46126274Sdes# elif HAVE_GSSAPI_GSSAPI_KRB5 47126274Sdes# include <gssapi/gssapi_krb5.h> 48126274Sdes# endif 49124208Sdes#endif 50124208Sdes 51124208Sdesstatic krb5_context krb_context = NULL; 52124208Sdes 53124208Sdes/* Initialise the krb5 library, for the stuff that GSSAPI won't do */ 54124208Sdes 55126274Sdesstatic int 56137015Sdesssh_gssapi_krb5_init(void) 57124208Sdes{ 58124208Sdes krb5_error_code problem; 59124208Sdes 60124208Sdes if (krb_context != NULL) 61124208Sdes return 1; 62124208Sdes 63124208Sdes problem = krb5_init_context(&krb_context); 64124208Sdes if (problem) { 65124208Sdes logit("Cannot initialize krb5 context"); 66124208Sdes return 0; 67124208Sdes } 68128456Sdes#ifdef KRB5_INIT_ETS 69124208Sdes krb5_init_ets(krb_context); 70128456Sdes#endif 71124208Sdes 72124208Sdes return 1; 73124208Sdes} 74124208Sdes 75124208Sdes/* Check if this user is OK to login. This only works with krb5 - other 76124208Sdes * GSSAPI mechanisms will need their own. 77124208Sdes * Returns true if the user is OK to log in, otherwise returns 0 78124208Sdes */ 79124208Sdes 80124208Sdesstatic int 81124208Sdesssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) 82124208Sdes{ 83124208Sdes krb5_principal princ; 84124208Sdes int retval; 85124208Sdes 86124208Sdes if (ssh_gssapi_krb5_init() == 0) 87124208Sdes return 0; 88124208Sdes 89124208Sdes if ((retval = krb5_parse_name(krb_context, client->exportedname.value, 90124208Sdes &princ))) { 91124208Sdes logit("krb5_parse_name(): %.100s", 92124208Sdes krb5_get_err_text(krb_context, retval)); 93124208Sdes return 0; 94124208Sdes } 95124208Sdes if (krb5_kuserok(krb_context, princ, name)) { 96124208Sdes retval = 1; 97124208Sdes logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", 98124208Sdes name, (char *)client->displayname.value); 99124208Sdes } else 100124208Sdes retval = 0; 101124208Sdes 102124208Sdes krb5_free_principal(krb_context, princ); 103124208Sdes return retval; 104124208Sdes} 105124208Sdes 106124208Sdes 107124208Sdes/* This writes out any forwarded credentials from the structure populated 108124208Sdes * during userauth. Called after we have setuid to the user */ 109124208Sdes 110124208Sdesstatic void 111124208Sdesssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 112124208Sdes{ 113124208Sdes krb5_ccache ccache; 114124208Sdes krb5_error_code problem; 115124208Sdes krb5_principal princ; 116124208Sdes OM_uint32 maj_status, min_status; 117126274Sdes int len; 118124208Sdes 119124208Sdes if (client->creds == NULL) { 120124208Sdes debug("No credentials stored"); 121124208Sdes return; 122124208Sdes } 123124208Sdes 124124208Sdes if (ssh_gssapi_krb5_init() == 0) 125124208Sdes return; 126124208Sdes 127124208Sdes#ifdef HEIMDAL 128124208Sdes if ((problem = krb5_cc_gen_new(krb_context, &krb5_fcc_ops, &ccache))) { 129124208Sdes logit("krb5_cc_gen_new(): %.100s", 130124208Sdes krb5_get_err_text(krb_context, problem)); 131124208Sdes return; 132124208Sdes } 133124208Sdes#else 134124208Sdes { 135124208Sdes int tmpfd; 136124208Sdes char ccname[40]; 137137015Sdes mode_t old_umask; 138126274Sdes 139126274Sdes snprintf(ccname, sizeof(ccname), 140124208Sdes "FILE:/tmp/krb5cc_%d_XXXXXX", geteuid()); 141126274Sdes 142137015Sdes old_umask = umask(0177); 143137015Sdes tmpfd = mkstemp(ccname + strlen("FILE:")); 144137015Sdes umask(old_umask); 145137015Sdes if (tmpfd == -1) { 146124208Sdes logit("mkstemp(): %.100s", strerror(errno)); 147124208Sdes problem = errno; 148124208Sdes return; 149124208Sdes } 150124208Sdes if (fchmod(tmpfd, S_IRUSR | S_IWUSR) == -1) { 151124208Sdes logit("fchmod(): %.100s", strerror(errno)); 152124208Sdes close(tmpfd); 153124208Sdes problem = errno; 154124208Sdes return; 155124208Sdes } 156124208Sdes close(tmpfd); 157124208Sdes if ((problem = krb5_cc_resolve(krb_context, ccname, &ccache))) { 158124208Sdes logit("krb5_cc_resolve(): %.100s", 159124208Sdes krb5_get_err_text(krb_context, problem)); 160124208Sdes return; 161124208Sdes } 162124208Sdes } 163124208Sdes#endif /* #ifdef HEIMDAL */ 164124208Sdes 165126274Sdes if ((problem = krb5_parse_name(krb_context, 166124208Sdes client->exportedname.value, &princ))) { 167124208Sdes logit("krb5_parse_name(): %.100s", 168124208Sdes krb5_get_err_text(krb_context, problem)); 169124208Sdes krb5_cc_destroy(krb_context, ccache); 170124208Sdes return; 171124208Sdes } 172124208Sdes 173124208Sdes if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) { 174124208Sdes logit("krb5_cc_initialize(): %.100s", 175124208Sdes krb5_get_err_text(krb_context, problem)); 176124208Sdes krb5_free_principal(krb_context, princ); 177124208Sdes krb5_cc_destroy(krb_context, ccache); 178124208Sdes return; 179124208Sdes } 180124208Sdes 181124208Sdes krb5_free_principal(krb_context, princ); 182124208Sdes 183126274Sdes if ((maj_status = gss_krb5_copy_ccache(&min_status, 184124208Sdes client->creds, ccache))) { 185124208Sdes logit("gss_krb5_copy_ccache() failed"); 186124208Sdes krb5_cc_destroy(krb_context, ccache); 187124208Sdes return; 188124208Sdes } 189124208Sdes 190124208Sdes client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); 191124208Sdes client->store.envvar = "KRB5CCNAME"; 192126274Sdes len = strlen(client->store.filename) + 6; 193126274Sdes client->store.envval = xmalloc(len); 194126274Sdes snprintf(client->store.envval, len, "FILE:%s", client->store.filename); 195124208Sdes 196124208Sdes#ifdef USE_PAM 197124208Sdes if (options.use_pam) 198126274Sdes do_pam_putenv(client->store.envvar, client->store.envval); 199124208Sdes#endif 200124208Sdes 201124208Sdes krb5_cc_close(krb_context, ccache); 202124208Sdes 203124208Sdes return; 204124208Sdes} 205124208Sdes 206124208Sdesssh_gssapi_mech gssapi_kerberos_mech = { 207124208Sdes "toWM5Slw5Ew8Mqkay+al2g==", 208124208Sdes "Kerberos", 209124208Sdes {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, 210124208Sdes NULL, 211124208Sdes &ssh_gssapi_krb5_userok, 212124208Sdes NULL, 213124208Sdes &ssh_gssapi_krb5_storecreds 214124208Sdes}; 215124208Sdes 216124208Sdes#endif /* KRB5 */ 217124208Sdes 218124208Sdes#endif /* GSSAPI */ 219