1255767Sdes/* $OpenBSD: gss-serv-krb5.c,v 1.8 2013/07/20 01:55:13 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 32162852Sdes#include <sys/types.h> 33162852Sdes 34162852Sdes#include <stdarg.h> 35162852Sdes#include <string.h> 36162852Sdes 37162852Sdes#include "xmalloc.h" 38162852Sdes#include "key.h" 39162852Sdes#include "hostfile.h" 40124208Sdes#include "auth.h" 41124208Sdes#include "log.h" 42295367Sdes#include "misc.h" 43124208Sdes#include "servconf.h" 44124208Sdes 45162852Sdes#include "buffer.h" 46124208Sdes#include "ssh-gss.h" 47124208Sdes 48124208Sdesextern ServerOptions options; 49124208Sdes 50124208Sdes#ifdef HEIMDAL 51126274Sdes# include <krb5.h> 52124208Sdes#endif 53255767Sdes#ifdef HAVE_GSSAPI_KRB5_H 54255767Sdes# include <gssapi_krb5.h> 55255767Sdes#elif HAVE_GSSAPI_GSSAPI_KRB5_H 56255767Sdes# include <gssapi/gssapi_krb5.h> 57255767Sdes#endif 58124208Sdes 59124208Sdesstatic krb5_context krb_context = NULL; 60124208Sdes 61124208Sdes/* Initialise the krb5 library, for the stuff that GSSAPI won't do */ 62124208Sdes 63126274Sdesstatic int 64137015Sdesssh_gssapi_krb5_init(void) 65124208Sdes{ 66124208Sdes krb5_error_code problem; 67124208Sdes 68124208Sdes if (krb_context != NULL) 69124208Sdes return 1; 70124208Sdes 71124208Sdes problem = krb5_init_context(&krb_context); 72124208Sdes if (problem) { 73124208Sdes logit("Cannot initialize krb5 context"); 74124208Sdes return 0; 75124208Sdes } 76124208Sdes 77124208Sdes return 1; 78124208Sdes} 79124208Sdes 80124208Sdes/* Check if this user is OK to login. This only works with krb5 - other 81124208Sdes * GSSAPI mechanisms will need their own. 82124208Sdes * Returns true if the user is OK to log in, otherwise returns 0 83124208Sdes */ 84124208Sdes 85124208Sdesstatic int 86124208Sdesssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) 87124208Sdes{ 88124208Sdes krb5_principal princ; 89124208Sdes int retval; 90255767Sdes const char *errmsg; 91124208Sdes 92124208Sdes if (ssh_gssapi_krb5_init() == 0) 93124208Sdes return 0; 94124208Sdes 95124208Sdes if ((retval = krb5_parse_name(krb_context, client->exportedname.value, 96124208Sdes &princ))) { 97255767Sdes errmsg = krb5_get_error_message(krb_context, retval); 98255767Sdes logit("krb5_parse_name(): %.100s", errmsg); 99255767Sdes krb5_free_error_message(krb_context, errmsg); 100124208Sdes return 0; 101124208Sdes } 102124208Sdes if (krb5_kuserok(krb_context, princ, name)) { 103124208Sdes retval = 1; 104124208Sdes logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", 105124208Sdes name, (char *)client->displayname.value); 106124208Sdes } else 107124208Sdes retval = 0; 108124208Sdes 109124208Sdes krb5_free_principal(krb_context, princ); 110124208Sdes return retval; 111124208Sdes} 112124208Sdes 113124208Sdes 114124208Sdes/* This writes out any forwarded credentials from the structure populated 115124208Sdes * during userauth. Called after we have setuid to the user */ 116124208Sdes 117124208Sdesstatic void 118124208Sdesssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 119124208Sdes{ 120124208Sdes krb5_ccache ccache; 121124208Sdes krb5_error_code problem; 122124208Sdes krb5_principal princ; 123124208Sdes OM_uint32 maj_status, min_status; 124126274Sdes int len; 125255767Sdes const char *errmsg; 126124208Sdes 127124208Sdes if (client->creds == NULL) { 128124208Sdes debug("No credentials stored"); 129124208Sdes return; 130124208Sdes } 131124208Sdes 132124208Sdes if (ssh_gssapi_krb5_init() == 0) 133124208Sdes return; 134124208Sdes 135124208Sdes#ifdef HEIMDAL 136262566Sdes# ifdef HAVE_KRB5_CC_NEW_UNIQUE 137255767Sdes if ((problem = krb5_cc_new_unique(krb_context, krb5_fcc_ops.prefix, 138255767Sdes NULL, &ccache)) != 0) { 139255767Sdes errmsg = krb5_get_error_message(krb_context, problem); 140255767Sdes logit("krb5_cc_new_unique(): %.100s", errmsg); 141262566Sdes# else 142262566Sdes if ((problem = krb5_cc_gen_new(krb_context, &krb5_fcc_ops, &ccache))) { 143262566Sdes logit("krb5_cc_gen_new(): %.100s", 144262566Sdes krb5_get_err_text(krb_context, problem)); 145262566Sdes# endif 146255767Sdes krb5_free_error_message(krb_context, errmsg); 147124208Sdes return; 148124208Sdes } 149124208Sdes#else 150149749Sdes if ((problem = ssh_krb5_cc_gen(krb_context, &ccache))) { 151255767Sdes errmsg = krb5_get_error_message(krb_context, problem); 152255767Sdes logit("ssh_krb5_cc_gen(): %.100s", errmsg); 153255767Sdes krb5_free_error_message(krb_context, errmsg); 154149749Sdes return; 155124208Sdes } 156124208Sdes#endif /* #ifdef HEIMDAL */ 157124208Sdes 158126274Sdes if ((problem = krb5_parse_name(krb_context, 159124208Sdes client->exportedname.value, &princ))) { 160255767Sdes errmsg = krb5_get_error_message(krb_context, problem); 161255767Sdes logit("krb5_parse_name(): %.100s", errmsg); 162255767Sdes krb5_free_error_message(krb_context, errmsg); 163124208Sdes return; 164124208Sdes } 165124208Sdes 166124208Sdes if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) { 167255767Sdes errmsg = krb5_get_error_message(krb_context, problem); 168255767Sdes logit("krb5_cc_initialize(): %.100s", errmsg); 169255767Sdes krb5_free_error_message(krb_context, errmsg); 170124208Sdes krb5_free_principal(krb_context, princ); 171124208Sdes krb5_cc_destroy(krb_context, ccache); 172124208Sdes return; 173124208Sdes } 174124208Sdes 175124208Sdes krb5_free_principal(krb_context, princ); 176124208Sdes 177126274Sdes if ((maj_status = gss_krb5_copy_ccache(&min_status, 178124208Sdes client->creds, ccache))) { 179124208Sdes logit("gss_krb5_copy_ccache() failed"); 180124208Sdes krb5_cc_destroy(krb_context, ccache); 181124208Sdes return; 182124208Sdes } 183124208Sdes 184124208Sdes client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); 185124208Sdes client->store.envvar = "KRB5CCNAME"; 186126274Sdes len = strlen(client->store.filename) + 6; 187126274Sdes client->store.envval = xmalloc(len); 188126274Sdes snprintf(client->store.envval, len, "FILE:%s", client->store.filename); 189124208Sdes 190124208Sdes#ifdef USE_PAM 191124208Sdes if (options.use_pam) 192126274Sdes do_pam_putenv(client->store.envvar, client->store.envval); 193124208Sdes#endif 194124208Sdes 195124208Sdes krb5_cc_close(krb_context, ccache); 196124208Sdes 197124208Sdes return; 198124208Sdes} 199124208Sdes 200124208Sdesssh_gssapi_mech gssapi_kerberos_mech = { 201124208Sdes "toWM5Slw5Ew8Mqkay+al2g==", 202124208Sdes "Kerberos", 203124208Sdes {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, 204124208Sdes NULL, 205124208Sdes &ssh_gssapi_krb5_userok, 206124208Sdes NULL, 207124208Sdes &ssh_gssapi_krb5_storecreds 208124208Sdes}; 209124208Sdes 210124208Sdes#endif /* KRB5 */ 211124208Sdes 212124208Sdes#endif /* GSSAPI */ 213