155682Smarkm/* 272445Sassar * Copyright (c) 1998 - 2001 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "ftpd_locl.h" 3555682Smarkm#include <gssapi.h> 3655682Smarkm#include <krb5.h> 3755682Smarkm 38178825SdfrRCSID("$Id: gss_userok.c 21222 2007-06-20 10:11:14Z lha $"); 3955682Smarkm 4055682Smarkm/* XXX a bit too much of krb5 dependency here... 4155682Smarkm What is the correct way to do this? 4255682Smarkm */ 4355682Smarkm 44178825Sdfrstruct gss_krb5_data { 45178825Sdfr krb5_context context; 46178825Sdfr}; 4755682Smarkm 4855682Smarkm/* XXX sync with gssapi.c */ 4955682Smarkmstruct gss_data { 5055682Smarkm gss_ctx_id_t context_hdl; 5155682Smarkm char *client_name; 5272445Sassar gss_cred_id_t delegated_cred_handle; 53178825Sdfr void *mech_data; 5455682Smarkm}; 5555682Smarkm 5655682Smarkmint gss_userok(void*, char*); /* to keep gcc happy */ 57178825Sdfrint gss_session(void*, char*); /* to keep gcc happy */ 5855682Smarkm 5955682Smarkmint 6055682Smarkmgss_userok(void *app_data, char *username) 6155682Smarkm{ 6255682Smarkm struct gss_data *data = app_data; 63178825Sdfr krb5_error_code ret; 64178825Sdfr krb5_principal client; 65178825Sdfr struct gss_krb5_data *kdata; 66178825Sdfr 67178825Sdfr kdata = calloc(1, sizeof(struct gss_krb5_data)); 68178825Sdfr if (kdata == NULL) 69178825Sdfr return 1; 70178825Sdfr data->mech_data = kdata; 71178825Sdfr 72178825Sdfr ret = krb5_init_context(&(kdata->context)); 73178825Sdfr if (ret) { 74178825Sdfr free(kdata); 75178825Sdfr return 1; 76178825Sdfr } 77178825Sdfr 78178825Sdfr ret = krb5_parse_name(kdata->context, data->client_name, &client); 79178825Sdfr if(ret) { 80178825Sdfr krb5_free_context(kdata->context); 81178825Sdfr free(kdata); 82178825Sdfr return 1; 83178825Sdfr } 84178825Sdfr ret = krb5_kuserok(kdata->context, client, username); 85178825Sdfr if (!ret) { 86178825Sdfr krb5_free_principal(kdata->context, client); 87178825Sdfr krb5_free_context(kdata->context); 88178825Sdfr free(kdata); 89178825Sdfr return 1; 90178825Sdfr } 9172445Sassar 92178825Sdfr ret = 0; 93178825Sdfr krb5_free_principal(kdata->context, client); 94178825Sdfr return ret; 95178825Sdfr} 96178825Sdfr 97178825Sdfrint 98178825Sdfrgss_session(void *app_data, char *username) 99178825Sdfr{ 100178825Sdfr struct gss_data *data = app_data; 101178825Sdfr krb5_error_code ret; 102178825Sdfr OM_uint32 minor_status; 103178825Sdfr struct gss_krb5_data *kdata; 104178825Sdfr 105178825Sdfr ret = 0; 106178825Sdfr 107178825Sdfr kdata = (struct gss_krb5_data *)(data->mech_data); 10872445Sassar 109178825Sdfr /* more of krb-depend stuff :-( */ 110178825Sdfr /* gss_add_cred() ? */ 111178825Sdfr if (data->delegated_cred_handle != GSS_C_NO_CREDENTIAL) { 112178825Sdfr krb5_ccache ccache = NULL; 113178825Sdfr const char* ticketfile; 114178825Sdfr struct passwd *kpw; 115178825Sdfr 116178825Sdfr ret = krb5_cc_gen_new(kdata->context, &krb5_fcc_ops, &ccache); 117178825Sdfr if (ret) 118178825Sdfr goto fail; 119178825Sdfr 120178825Sdfr ticketfile = krb5_cc_get_name(kdata->context, ccache); 12172445Sassar 122178825Sdfr ret = gss_krb5_copy_ccache(&minor_status, 123178825Sdfr data->delegated_cred_handle, 124178825Sdfr ccache); 125178825Sdfr if (ret) { 126178825Sdfr ret = 0; 127178825Sdfr goto fail; 128178825Sdfr } 12972445Sassar 130178825Sdfr do_destroy_tickets = 1; 131178825Sdfr 132178825Sdfr kpw = getpwnam(username); 13372445Sassar 134178825Sdfr if (kpw == NULL) { 135178825Sdfr unlink(ticketfile); 136178825Sdfr ret = 1; 137178825Sdfr goto fail; 138178825Sdfr } 13972445Sassar 140178825Sdfr chown (ticketfile, kpw->pw_uid, kpw->pw_gid); 14172445Sassar 142178825Sdfr if (asprintf(&k5ccname, "FILE:%s", ticketfile) != -1) { 143178825Sdfr esetenv ("KRB5CCNAME", k5ccname, 1); 144178825Sdfr } 145178825Sdfr afslog(NULL, 1); 146178825Sdfr fail: 147178825Sdfr if (ccache) 148178825Sdfr krb5_cc_close(kdata->context, ccache); 149178825Sdfr } 15072445Sassar 151178825Sdfr gss_release_cred(&minor_status, &data->delegated_cred_handle); 152178825Sdfr krb5_free_context(kdata->context); 153178825Sdfr free(kdata); 154178825Sdfr return ret; 15555682Smarkm} 156