⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne_auth.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    HTTP Authentication routines   Copyright (C) 1999-2004, Joe Orton <joe@manyfish.co.uk>   This library is free software; you can redistribute it and/or   modify it under the terms of the GNU Library General Public   License as published by the Free Software Foundation; either   version 2 of the License, or (at your option) any later version.      This library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Library General Public License for more details.   You should have received a copy of the GNU Library General Public   License along with this library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,   MA 02111-1307, USA*//* HTTP Authentication, as per RFC2617. *  * TODO: *  - Test auth-int support */#include "config.h"#include <sys/types.h>#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h> /* for getpid() */#endif#ifdef WIN32#include <windows.h> /* for GetCurrentThreadId() etc */#endif#ifdef NEON_SSL#include <openssl/rand.h>#endif#include <time.h>#include "ne_md5.h"#include "ne_dates.h"#include "ne_request.h"#include "ne_auth.h"#include "ne_string.h"#include "ne_utils.h"#include "ne_alloc.h"#include "ne_uri.h"#include "ne_i18n.h"#ifdef HAVE_GSSAPI#ifdef HAVE_GSSAPI_GSSAPI_H#include <gssapi/gssapi.h>#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H#include <gssapi/gssapi_generic.h>#endif#else#include <gssapi.h>#endif#endif/* TODO: should remove this eventually. Need it for * ne_pull_request_body. */#include "ne_private.h"#define HOOK_SERVER_ID "http://webdav.org/neon/hooks/server-auth"#define HOOK_PROXY_ID "http://webdav.org/neon/hooks/proxy-auth"/* The authentication scheme we are using */typedef enum {    auth_scheme_basic,    auth_scheme_digest,    auth_scheme_gssapi} auth_scheme;typedef enum {     auth_alg_md5,    auth_alg_md5_sess,    auth_alg_unknown} auth_algorithm;/* Selected method of qop which the client is using */typedef enum {    auth_qop_none,    auth_qop_auth,    auth_qop_auth_int} auth_qop;/* A challenge */struct auth_challenge {    auth_scheme scheme;    const char *realm;    const char *nonce;    const char *opaque;    unsigned int stale:1; /* if stale=true */    unsigned int got_qop:1; /* we were given a qop directive */    unsigned int qop_auth:1; /* "auth" token in qop attrib */    unsigned int qop_auth_int:1; /* "auth-int" token in qop attrib */    auth_algorithm alg;    struct auth_challenge *next;};static const struct auth_class {    const char *id, *req_hdr, *resp_hdr, *resp_info_hdr, *fail_msg;    int status_code, fail_code;} ah_server_class = {    HOOK_SERVER_ID,    "Authorization", "WWW-Authenticate", "Authentication-Info",    N_("Server was not authenticated correctly."), 401, NE_AUTH}, ah_proxy_class = {    HOOK_PROXY_ID,    "Proxy-Authorization", "Proxy-Authenticate", "Proxy-Authentication-Info",    N_("Proxy server was not authenticated correctly."), 407, NE_PROXYAUTH };/* Authentication session state. */typedef struct {    ne_session *sess;    /* Which context will auth challenges be accepted? */    enum {        AUTH_ANY, /* ignore nothing. */        AUTH_CONNECT, /* only in response to a CONNECT request. */        AUTH_NOTCONNECT /* only in non-CONNECT responsees */    } context;        /* Specifics for server/proxy auth. FIXME: need a better field     * name! */    const struct auth_class *spec;        /* The scheme used for this authentication session */    auth_scheme scheme;    /* The callback used to request new username+password */    ne_auth_creds creds;    void *userdata;    /*** Session details ***/    /* The username and password we are using to authenticate with */    char username[NE_ABUFSIZ];    /* Whether we CAN supply authentication at the moment */    unsigned int can_handle:1;    /* This used for Basic auth */    char *basic; #ifdef HAVE_GSSAPI    /* This used for GSSAPI auth */    char *gssapi_token;#endif    /* These all used for Digest auth */    char *realm;    char *nonce;    char *cnonce;    char *opaque;    auth_qop qop;    auth_algorithm alg;    unsigned int nonce_count;    /* The ASCII representation of the session's H(A1) value */    char h_a1[33];    /* Temporary store for half of the Request-Digest     * (an optimisation - used in the response-digest calculation) */    struct ne_md5_ctx stored_rdig;    /* Details of server... needed to reconstruct absoluteURI's when     * necessary */    const char *host;    const char *uri_scheme;    unsigned int port;    int attempt;} auth_session;struct auth_request {    /*** Per-request details. ***/    ne_request *request; /* the request object. */    /* The method and URI we are using for the current request */    const char *uri;    const char *method;    /* Whether we WILL supply authentication for this request or not */    unsigned int will_handle:1;    /* Used for calculation of H(entity-body) of the response */    struct ne_md5_ctx response_body;    /* Results of response-header callbacks */    char *auth_hdr, *auth_info_hdr;};static void clean_session(auth_session *sess) {    sess->can_handle = 0;    NE_FREE(sess->basic);    NE_FREE(sess->nonce);    NE_FREE(sess->cnonce);    NE_FREE(sess->opaque);    NE_FREE(sess->realm);#ifdef HAVE_GSSAPI    NE_FREE(sess->gssapi_token);#endif}/* Returns client nonce string. */static char *get_cnonce(void) {    char ret[33];    unsigned char data[256], tmp[16];    struct ne_md5_ctx hash;    ne_md5_init_ctx(&hash);#ifdef NEON_SSL    if (RAND_status() == 1 && RAND_pseudo_bytes(data, sizeof data) >= 0)	ne_md5_process_bytes(data, sizeof data, &hash);    else {#endif    /* Fallback sources of random data: all bad, but no good sources     * are available. */    /* Uninitialized stack data; yes, happy valgrinders, this is     * supposed to be here. */    ne_md5_process_bytes(data, sizeof data, &hash);    #ifdef HAVE_GETTIMEOFDAY    {	struct timeval tv;	if (gettimeofday(&tv, NULL) == 0)	    ne_md5_process_bytes(&tv, sizeof tv, &hash);    }#else /* HAVE_GETTIMEOFDAY */    {	time_t t = time(NULL);	ne_md5_process_bytes(&t, sizeof t, &hash);    }#endif    {#ifdef WIN32	DWORD pid = GetCurrentThreadId();#else	pid_t pid = getpid();#endif	ne_md5_process_bytes(&pid, sizeof pid, &hash);    }#ifdef NEON_SSL    }#endif        ne_md5_finish_ctx(&hash, tmp);    ne_md5_to_ascii(tmp, ret);    return ne_strdup(ret);}static int get_credentials(auth_session *sess, char *pwbuf) {    return sess->creds(sess->userdata, sess->realm, sess->attempt++,		       sess->username, pwbuf);}/* Examine a Basic auth challenge. * Returns 0 if an valid challenge, else non-zero. */static int basic_challenge(auth_session *sess, struct auth_challenge *parms) {    char *tmp, password[NE_ABUFSIZ];    /* Verify challenge... must have a realm */    if (parms->realm == NULL) {	return -1;    }    NE_DEBUG(NE_DBG_HTTPAUTH, "Got Basic challenge with realm [%s]\n", 	     parms->realm);    clean_session(sess);        sess->realm = ne_strdup(parms->realm);    if (get_credentials(sess, password)) {	/* Failed to get credentials */	return -1;    }    sess->scheme = auth_scheme_basic;    tmp = ne_concat(sess->username, ":", password, NULL);    sess->basic = ne_base64((unsigned char *)tmp, strlen(tmp));    ne_free(tmp);    /* Paranoia. */    memset(password, 0, sizeof password);    return 0;}/* Add Basic authentication credentials to a request */static char *request_basic(auth_session *sess) {    return ne_concat("Basic ", sess->basic, "\r\n", NULL);}#ifdef HAVE_GSSAPI/* Add GSSAPI authentication credentials to a request */static char *request_gssapi(auth_session *sess) {    return ne_concat("Negotiate ", sess->gssapi_token, "\r\n", NULL);}static int get_gss_name(gss_name_t *server, auth_session *sess){    unsigned int major_status, minor_status;    gss_buffer_desc token = GSS_C_EMPTY_BUFFER;    token.value = ne_concat("HTTP@", sess->sess->server.hostname, NULL);    token.length = strlen(token.value);    major_status = gss_import_name(&minor_status, &token,                                   GSS_C_NT_HOSTBASED_SERVICE,                                   server);    return GSS_ERROR(major_status) ? -1 : 0;}/* Examine a GSSAPI auth challenge; returns 0 if a valid challenge, * else non-zero. */static int gssapi_challenge(auth_session *sess, struct auth_challenge *parms) {    gss_ctx_id_t context;    gss_name_t server_name;    unsigned int major_status, minor_status;    gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;    gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;    clean_session(sess);    if (get_gss_name(&server_name, sess))        return -1;    major_status = gss_init_sec_context(&minor_status,                                        GSS_C_NO_CREDENTIAL,                                        &context,                                        server_name,                                        GSS_C_NO_OID,                                        0,                                        GSS_C_INDEFINITE,                                        GSS_C_NO_CHANNEL_BINDINGS,                                        &input_token,                                        NULL,                                        &output_token,                                        NULL,                                        NULL);    gss_release_name(&minor_status, &server_name);    if (GSS_ERROR(major_status)) {        NE_DEBUG(NE_DBG_HTTPAUTH, "gss_init_sec_context failed.\n");        return -1;    }        if (output_token.length == 0)        return -1;    sess->gssapi_token = ne_base64(output_token.value, output_token.length);    gss_release_buffer(&major_status, &output_token);    NE_DEBUG(NE_DBG_HTTPAUTH,              "Base64 encoded GSSAPI challenge: %s.\n", sess->gssapi_token);    sess->scheme = auth_scheme_gssapi;    return 0;}#endif/* Examine a digest challenge: return 0 if it is a valid Digest challenge, * else non-zero. */static int digest_challenge(auth_session *sess, struct auth_challenge *parms) 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -