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

📄 sasl.c

📁 这是一个完全开放的
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, *                    Ryan Eatmon, Robert Norris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA *//* SASL authentication handler */#include "sx.h"#include "ssl.h"#include "sasl.h"#define _sasl_err_ABORTED               "aborted"#define _sasl_err_BAD_PROTOCOL          "bad-protocol"#define _sasl_err_INCORRECT_ENCODING    "incorrect-encoding"#define _sasl_err_INVALID_AUTHZID       "invalid-authzid"#define _sasl_err_INVALID_MECHANISM     "invalid-mechanism"#define _sasl_err_MECH_TOO_WEAK         "mechanism-too-weak"#define _sasl_err_NOT_AUTHORIZED        "not-authorized"#define _sasl_err_TEMPORARY_FAILURE     "temporary-authentication-failure"/** move the stream to the auth state */void _sx_sasl_open(sx_t s, scod_t sd) {    char *method;        /* get the method */    method = (char *) malloc(sizeof(char) * (strlen(sd->mech->name) + 6));    sprintf(method, "SASL/%s", sd->mech->name);    /* schwing! */    sx_auth(s, method, sd->authzid);    free(method);}/** make the stream suthenticated second time round */static void _sx_sasl_stream(sx_t s, sx_plugin_t p) {    scod_t sd = (scod_t) s->plugin_data[p->index];    /* do nothing the first time */    if(sd == NULL)        return;    /* are we auth'd? */    if(!sd->authd) {        _sx_debug(ZONE, "not auth'd, not advancing to auth'd state yet");        return;    }    /* otherwise, its auth time */    _sx_sasl_open(s, sd);}static void _sx_sasl_features(sx_t s, sx_plugin_t p, nad_t nad) {    _sx_sasl_t ctx = (_sx_sasl_t) p->private;    scod_t sd = (scod_t) s->plugin_data[p->index];    int i, ns;    if(s->type != type_SERVER)        return;    if(sd != NULL && sd->authd) {        _sx_debug(ZONE, "already auth'd, not offering sasl mechanisms");        return;    }    if(!(s->flags & SX_SASL_OFFER)) {        _sx_debug(ZONE, "application didn't ask us to offer sasl, so we won't");        return;    }    if(!(s->flags & SX_SASL_MECH_ANONYMOUS || s->flags & SX_SASL_MECH_PLAIN || s->flags & SX_SASL_MECH_DIGESTMD5)) {        _sx_debug(ZONE, "application didn't provide any mechanisms we can offer");        return;    }#ifdef HAVE_SSL    if((s->flags & SX_SSL_STARTTLS_REQUIRE) && s->ssf == 0) {        _sx_debug(ZONE, "ssl not established yet but the app requires it, not offering mechanisms");        return;    }#endif        _sx_debug(ZONE, "offering sasl mechanisms");        ns = nad_add_namespace(nad, uri_SASL, NULL);    nad_append_elem(nad, ns, "mechanisms", 1);    for(i = 0; i < ctx->scod_ctx->nmechs; i++)        if(ctx->scod_ctx->mechs[i]->flags == 0 || ctx->flags & ctx->scod_ctx->mechs[i]->flags) {            if((s->flags & SX_SASL_MECH_ANONYMOUS && strcmp("ANONYMOUS", ctx->scod_ctx->names[i]) == 0) ||               (s->flags & SX_SASL_MECH_PLAIN && strcmp("PLAIN", ctx->scod_ctx->names[i]) == 0) ||               (s->flags & SX_SASL_MECH_DIGESTMD5 && strcmp("DIGEST-MD5", ctx->scod_ctx->names[i]) == 0)) {                _sx_debug(ZONE, "offering mechanism: %s", ctx->scod_ctx->names[i]);                nad_append_elem(nad, ns, "mechanism", 2);                nad_append_cdata(nad, ctx->scod_ctx->names[i], strlen(ctx->scod_ctx->names[i]), 3);            }        }}/** utility: generate a success nad */static nad_t _sx_sasl_success(sx_t s) {    nad_t nad;    int ns;    nad = nad_new(s->nad_cache);    ns = nad_add_namespace(nad, uri_SASL, NULL);    nad_append_elem(nad, ns, "success", 0);    return nad;}/** utility: generate a failure nad */static nad_t _sx_sasl_failure(sx_t s, const char *err) {    nad_t nad;    int ns;    nad = nad_new(s->nad_cache);    ns = nad_add_namespace(nad, uri_SASL, NULL);    nad_append_elem(nad, ns, "failure", 0);    if(err != NULL)        nad_append_elem(nad, ns, err, 1);    return nad;}/** utility: generate a challenge nad */static nad_t _sx_sasl_challenge(sx_t s, char *data, int dlen) {    nad_t nad;    int ns;    nad = nad_new(s->nad_cache);    ns = nad_add_namespace(nad, uri_SASL, NULL);    nad_append_elem(nad, ns, "challenge", 0);    if(data != NULL)        nad_append_cdata(nad, data, dlen, 1);    return nad;}/** utility: generate a response nad */static nad_t _sx_sasl_response(sx_t s, char *data, int dlen) {    nad_t nad;    int ns;    nad = nad_new(s->nad_cache);    ns = nad_add_namespace(nad, uri_SASL, NULL);    nad_append_elem(nad, ns, "response", 0);    if(data != NULL)        nad_append_cdata(nad, data, dlen, 1);    return nad;}/** utility: generate an abort nad */static nad_t _sx_sasl_abort(sx_t s) {    nad_t nad;    int ns;    nad = nad_new(s->nad_cache);    ns = nad_add_namespace(nad, uri_SASL, NULL);    nad_append_elem(nad, ns, "abort", 0);    return nad;}/** utility: decode incoming handshake data */static void _sx_sasl_decode(char *in, int inlen, char **out, int *outlen) {    *outlen = ap_base64decode_len(in, inlen);    *out = (char *) malloc(sizeof(char) * (*outlen + 1));    ap_base64decode(*out, in, inlen);}/** utility: encode outgoing handshake data */static void _sx_sasl_encode(char *in, int inlen, char **out, int *outlen) {    *outlen = ap_base64encode_len(inlen);    *out = (char *) malloc(sizeof(char) * *outlen);    ap_base64encode(*out, in, inlen);    (*outlen)--;}/** auth done, restart the stream */static void _sx_sasl_notify_success(sx_t s, void *arg) {    _sx_debug(ZONE, "auth completed, resetting");    _sx_reset(s);    sx_server_init(s, s->flags);}/** process handshake packets from the client */static void _sx_sasl_client_process(sx_t s, sx_plugin_t p, scod_t sd, char *mech, char *in, int inlen) {    _sx_sasl_t ctx = (_sx_sasl_t) p->private;    char realm[256];    char *buf, *out;    int buflen, outlen, ret;    if(mech != NULL) {        _sx_debug(ZONE, "auth request from client (mechanism=%s)", mech);        if(!((s->flags & SX_SASL_MECH_ANONYMOUS && strcmp("ANONYMOUS", mech) == 0) ||             (s->flags & SX_SASL_MECH_PLAIN && strcmp("PLAIN", mech) == 0) ||             (s->flags & SX_SASL_MECH_DIGESTMD5 && strcmp("DIGEST-MD5", mech) == 0))) {             _sx_debug(ZONE, "client requested mechanism that we didn't offer");             _sx_nad_write(s, _sx_sasl_failure(s, _sasl_err_INVALID_MECHANISM), 0);             return;        }        /* startup */        sd = scod_new(ctx->scod_ctx, sd_type_SERVER);        if(sd == NULL) {            _sx_debug(ZONE, "scod_new failed, no sasl for this conn");            _sx_nad_write(s, _sx_sasl_failure(s, _sasl_err_TEMPORARY_FAILURE), 0);            return;        }        _sx_debug(ZONE, "sasl context initialised for %d", s->tag);        s->plugin_data[p->index] = (void *) sd;        sd->app_private = (void *) s;        /* get the realm */        realm[0] = '\0';        assert((int) ctx->cb);        (ctx->cb)(sx_sasl_cb_GET_REALM, (void *) s, (void **) realm, sd, ctx->cbarg);        /* decode and process */        _sx_sasl_decode(in, inlen, &buf, &buflen);        ret = scod_server_start(sd, mech, realm, buf, buflen, &out, &outlen);    }    else {        _sx_debug(ZONE, "response from client");        /* decode and process */        _sx_sasl_decode(in, inlen, &buf, &buflen);        ret = scod_server_step(sd, buf, buflen, &out, &outlen);    }    if(buf != NULL) free(buf);    /* auth completed */    if(ret == sd_SUCCESS) {        _sx_debug(ZONE, "sasl handshake completed");        if(out != NULL) free(out);        /* send success */        _sx_nad_write(s, _sx_sasl_success(s), 0);        /* set a notify on the success nad buffer */        ((sx_buf_t) s->wbufq->front->data)->notify = _sx_sasl_notify_success;        ((sx_buf_t) s->wbufq->front->data)->notify_arg = (void *) p;        return;    }    /* in progress */    if(ret == sd_CONTINUE) {        _sx_debug(ZONE, "sasl handshake in progress (challenge: %.*s)", outlen, out);        /* encode the challenge */        _sx_sasl_encode(out, outlen, &buf, &buflen);                if(out != NULL) free(out);        _sx_nad_write(s, _sx_sasl_challenge(s, buf, buflen), 0);        free(buf);        return;    }    if(out != NULL) free(out);    /* its over */    _sx_debug(ZONE, "sasl handshake failed: (%d)", ret);    /* !!! check ret and flag error appropriately */    _sx_nad_write(s, _sx_sasl_failure(s, _sasl_err_TEMPORARY_FAILURE), 0);}/** process handshake packets from the server */static void _sx_sasl_server_process(sx_t s, sx_plugin_t p, scod_t sd, char *in, int inlen) {    char *buf, *out;    int buflen, outlen, ret;    _sx_debug(ZONE, "challenge from client");    /* decode the response */    _sx_sasl_decode(in, inlen, &buf, &buflen);    /* process the data */    ret = scod_client_step(sd, buf, buflen, &out, &outlen);    if(buf != NULL) free(buf);    /* in progress */    if(ret == sd_SUCCESS || ret == sd_CONTINUE) {        _sx_debug(ZONE, "sasl handshake in progress (response: %.*s)", outlen, out);        /* encode the response */        _sx_sasl_encode(out, outlen, &buf, &buflen);

⌨️ 快捷键说明

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