/*
* Wyllys Ingersoll <wyllys.ingersoll@sun.com>
*
* Based on work by
* Daniel Kouril <kouril@users.sourceforge.net>
* James E. Robinson, III <james@ncstate.net>
* Daniel Henninger <daniel@ncsu.edu>
* Ludek Sulak <xsulak@fi.muni.cz>
*/
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
*
* Portions of this software are based upon public domain software
* originally written at the National Center for Supercomputing Applications,
* University of Illinois, Urbana-Champaign.
*/
/*
*/
#include <strings.h>
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
#include "http_request.h"
#include "ap_config.h"
#include "apr_base64.h"
#include "apr_lib.h"
#include "apr_time.h"
#include "apr_errno.h"
#include "apr_global_mutex.h"
#include "apr_strings.h"
#include "ap_compat.h"
#include <gssapi/gssapi_ext.h>
static void *gss_create_dir_config(apr_pool_t *, char *);
int gss_authenticate(request_rec *);
typedef struct {
char *gss_service_name;
char *keytab_file;
int gss_debug;
const char *name)
{
return NULL;
}
const char *file)
{
return NULL;
}
const char *debugflag)
{
return NULL;
}
OR_AUTHCFG, "Service name used for authentication."),
"Location of Kerberos V5 keytab file."),
"Enable debug logging in error_log"),
{ NULL }
};
static void
{
}
gss_create_dir_config, /* dir config creater */
NULL, /* dir merger --- default is to override */
NULL, /* server config */
NULL, /* merge server config */
gss_auth_cmds, /* command apr_table_t */
gss_register_hooks /* register hooks */
};
typedef struct {
static void *
{
return rec;
}
const request_rec *r, const char *fmt, ...)
{
}
/*********************************************************************
* GSSAPI Authentication
********************************************************************/
static const char *
{
do {
&msg);
break;
NULL);
&msg);
}
return (err_msg);
}
static int
{
return 0;
(void) gss_delete_sec_context(&minor_status,
}
}
return 0;
}
static int
{
int ret = 0;
"acquire_server_creds for %s", buf);
&server_name);
if (GSS_ERROR(major_status)) {
"gss_import_name() failed"));
return (HTTP_INTERNAL_SERVER_ERROR);
}
if (GSS_ERROR(major_status)) {
"gss_acquire_cred() failed"));
}
return (ret);
}
static int
const char *auth_line, char **negotiate_ret_value)
{
int ret = 0;
"authenticate_user_gss called");
*negotiate_ret_value = (char *)"";
if (gss_connection == NULL) {
if (gss_connection == NULL) {
"apr_pcalloc() failed (not enough memory)");
goto end;
}
}
if (conf->keytab_file) {
char *ktname;
/*
* We don't use the ap_* calls here, since the string
* passed to putenv() will become part of the enviroment
* and shouldn't be free()ed by apache.
*/
"malloc() failed: not enough memory");
goto end;
}
/*
* Put the keytab name in the environment so that Kerberos
* knows where to look later.
*/
}
/* ap_getword() shifts parameter */
if (auth_param == NULL) {
"No Authorization parameter in request from client");
goto end;
}
"apr_pcalloc() failed (not enough memory)");
goto end;
}
}
mechstr = "<unknown>";
}
"Client wants GSS mech: %s", mechstr);
/* Get creds using the mechanism that the client requested */
if (ret)
goto end;
}
/*
* Try to display the server creds information.
*/
if (major_status == GSS_S_COMPLETE) {
}
if (major_status == GSS_S_COMPLETE) {
"got server creds for: %.*s",
}
}
NULL,
NULL,
NULL,
if (output_token.length) {
"apr_pcalloc() failed (not enough memory)");
goto end;
}
}
if (GSS_ERROR(major_status)) {
"gss_accept_sec_context() failed"));
/* Don't offer the Negotiate method again if call to GSS layer failed */
goto end;
}
if (major_status == GSS_S_CONTINUE_NEEDED) {
/*
* Some GSSAPI mechanisms may require multiple iterations to
* establish authentication. Most notably, when MUTUAL_AUTHENTICATION
* flag is used, multiple round trips are needed.
*/
goto end;
}
if (client_name != GSS_C_NO_NAME) {
&name_token, NULL);
if (GSS_ERROR(major_status)) {
"gss_export_name() failed"));
goto end;
}
if (name_token.length) {
}
"Authenticated user: %s",
}
r->ap_auth_type = "Negotiate";
end:
if (delegated_cred)
if (output_token.length)
if (client_name != GSS_C_NO_NAME)
return ret;
}
static int
{
return 0;
}
static void
char *negotiate_ret_value)
{
int set_basic = 0;
char *negoauth_param;
/* get the user realm specified in .htaccess */
auth_name = ap_auth_name(r);
"note_gss_auth_failure: auth_name = %s",
if (negotiate_ret_value != NULL) {
}
}
int
{
int ret;
char *negotiate_ret_value;
/* get the type specified in .htaccess */
type = ap_auth_type(r);
"gss_authenticate: type = %s", type);
return DECLINED;
}
/* get what the user sent us in the HTTP header */
if (!auth_line) {
"No authentication data found");
return HTTP_UNAUTHORIZED;
}
if (already_succeeded(r))
return last_return;
} else {
}
if (ret == HTTP_UNAUTHORIZED) {
"Authentication failed.");
}
last_return = ret;
return ret;
}