gss-serv-krb5.c revision 124208
1124208Sdes/* $OpenBSD: gss-serv-krb5.c,v 1.1 2003/08/22 10:56:09 markus 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 42124208Sdes#include <krb5.h> 43124208Sdes#else 44124208Sdes#include <gssapi_krb5.h> 45124208Sdes#endif 46124208Sdes 47124208Sdesstatic krb5_context krb_context = NULL; 48124208Sdes 49124208Sdes/* Initialise the krb5 library, for the stuff that GSSAPI won't do */ 50124208Sdes 51124208Sdesstatic int 52124208Sdesssh_gssapi_krb5_init() 53124208Sdes{ 54124208Sdes krb5_error_code problem; 55124208Sdes 56124208Sdes if (krb_context != NULL) 57124208Sdes return 1; 58124208Sdes 59124208Sdes problem = krb5_init_context(&krb_context); 60124208Sdes if (problem) { 61124208Sdes logit("Cannot initialize krb5 context"); 62124208Sdes return 0; 63124208Sdes } 64124208Sdes krb5_init_ets(krb_context); 65124208Sdes 66124208Sdes return 1; 67124208Sdes} 68124208Sdes 69124208Sdes/* Check if this user is OK to login. This only works with krb5 - other 70124208Sdes * GSSAPI mechanisms will need their own. 71124208Sdes * Returns true if the user is OK to log in, otherwise returns 0 72124208Sdes */ 73124208Sdes 74124208Sdesstatic int 75124208Sdesssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) 76124208Sdes{ 77124208Sdes krb5_principal princ; 78124208Sdes int retval; 79124208Sdes 80124208Sdes if (ssh_gssapi_krb5_init() == 0) 81124208Sdes return 0; 82124208Sdes 83124208Sdes if ((retval = krb5_parse_name(krb_context, client->exportedname.value, 84124208Sdes &princ))) { 85124208Sdes logit("krb5_parse_name(): %.100s", 86124208Sdes krb5_get_err_text(krb_context, retval)); 87124208Sdes return 0; 88124208Sdes } 89124208Sdes if (krb5_kuserok(krb_context, princ, name)) { 90124208Sdes retval = 1; 91124208Sdes logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", 92124208Sdes name, (char *)client->displayname.value); 93124208Sdes } else 94124208Sdes retval = 0; 95124208Sdes 96124208Sdes krb5_free_principal(krb_context, princ); 97124208Sdes return retval; 98124208Sdes} 99124208Sdes 100124208Sdes 101124208Sdes/* This writes out any forwarded credentials from the structure populated 102124208Sdes * during userauth. Called after we have setuid to the user */ 103124208Sdes 104124208Sdesstatic void 105124208Sdesssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 106124208Sdes{ 107124208Sdes krb5_ccache ccache; 108124208Sdes krb5_error_code problem; 109124208Sdes krb5_principal princ; 110124208Sdes OM_uint32 maj_status, min_status; 111124208Sdes 112124208Sdes if (client->creds == NULL) { 113124208Sdes debug("No credentials stored"); 114124208Sdes return; 115124208Sdes } 116124208Sdes 117124208Sdes if (ssh_gssapi_krb5_init() == 0) 118124208Sdes return; 119124208Sdes 120124208Sdes#ifdef HEIMDAL 121124208Sdes if ((problem = krb5_cc_gen_new(krb_context, &krb5_fcc_ops, &ccache))) { 122124208Sdes logit("krb5_cc_gen_new(): %.100s", 123124208Sdes krb5_get_err_text(krb_context, problem)); 124124208Sdes return; 125124208Sdes } 126124208Sdes#else 127124208Sdes { 128124208Sdes int tmpfd; 129124208Sdes char ccname[40]; 130124208Sdes 131124208Sdes snprintf(ccname, sizeof(ccname), 132124208Sdes "FILE:/tmp/krb5cc_%d_XXXXXX", geteuid()); 133124208Sdes 134124208Sdes if ((tmpfd = mkstemp(ccname + strlen("FILE:"))) == -1) { 135124208Sdes logit("mkstemp(): %.100s", strerror(errno)); 136124208Sdes problem = errno; 137124208Sdes return; 138124208Sdes } 139124208Sdes if (fchmod(tmpfd, S_IRUSR | S_IWUSR) == -1) { 140124208Sdes logit("fchmod(): %.100s", strerror(errno)); 141124208Sdes close(tmpfd); 142124208Sdes problem = errno; 143124208Sdes return; 144124208Sdes } 145124208Sdes close(tmpfd); 146124208Sdes if ((problem = krb5_cc_resolve(krb_context, ccname, &ccache))) { 147124208Sdes logit("krb5_cc_resolve(): %.100s", 148124208Sdes krb5_get_err_text(krb_context, problem)); 149124208Sdes return; 150124208Sdes } 151124208Sdes } 152124208Sdes#endif /* #ifdef HEIMDAL */ 153124208Sdes 154124208Sdes if ((problem = krb5_parse_name(krb_context, 155124208Sdes client->exportedname.value, &princ))) { 156124208Sdes logit("krb5_parse_name(): %.100s", 157124208Sdes krb5_get_err_text(krb_context, problem)); 158124208Sdes krb5_cc_destroy(krb_context, ccache); 159124208Sdes return; 160124208Sdes } 161124208Sdes 162124208Sdes if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) { 163124208Sdes logit("krb5_cc_initialize(): %.100s", 164124208Sdes krb5_get_err_text(krb_context, problem)); 165124208Sdes krb5_free_principal(krb_context, princ); 166124208Sdes krb5_cc_destroy(krb_context, ccache); 167124208Sdes return; 168124208Sdes } 169124208Sdes 170124208Sdes krb5_free_principal(krb_context, princ); 171124208Sdes 172124208Sdes if ((maj_status = gss_krb5_copy_ccache(&min_status, 173124208Sdes client->creds, ccache))) { 174124208Sdes logit("gss_krb5_copy_ccache() failed"); 175124208Sdes krb5_cc_destroy(krb_context, ccache); 176124208Sdes return; 177124208Sdes } 178124208Sdes 179124208Sdes client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); 180124208Sdes client->store.envvar = "KRB5CCNAME"; 181124208Sdes client->store.envval = xstrdup(client->store.filename); 182124208Sdes 183124208Sdes#ifdef USE_PAM 184124208Sdes if (options.use_pam) 185124208Sdes do_pam_putenv(client->store.envvar,client->store.envval); 186124208Sdes#endif 187124208Sdes 188124208Sdes krb5_cc_close(krb_context, ccache); 189124208Sdes 190124208Sdes return; 191124208Sdes} 192124208Sdes 193124208Sdesssh_gssapi_mech gssapi_kerberos_mech = { 194124208Sdes "toWM5Slw5Ew8Mqkay+al2g==", 195124208Sdes "Kerberos", 196124208Sdes {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, 197124208Sdes NULL, 198124208Sdes &ssh_gssapi_krb5_userok, 199124208Sdes NULL, 200124208Sdes &ssh_gssapi_krb5_storecreds 201124208Sdes}; 202124208Sdes 203124208Sdes#endif /* KRB5 */ 204124208Sdes 205124208Sdes#endif /* GSSAPI */ 206