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

📄 authreg_pipe.c

📁 这是一个完全开放的
💻 C
字号:
/* * 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 *//* * this is the fabled pipe authenticator. it forks and executes a * script, and talks to it via stdio. this is a great way to take * advantage of existing code (in any language) to do authentication and * registration. * * there is an example script, tools/pipe-auth.pl, which can be used to * get started writing a pipe module. the protocol is documented in * docs/dev/c2s-pipe-authenticator *//* * !!! this is highly experimental - be prepared for random acts of weirdness *     if you decide to use this. */#include "c2s.h"#ifdef STORAGE_PIPE#include <sys/wait.h>/** internal structure, holds our data */typedef struct moddata_st {    char    *exec;        pid_t   child;    int     in, out;} *moddata_t;static int _ar_pipe_write(authreg_t ar, int fd, char *msgfmt, ...){    va_list args;    char buf[1024];    int ret;    va_start(args, msgfmt);    vsnprintf(buf, 1024, msgfmt, args);    va_end(args);    log_debug(ZONE, "writing to pipe: %s", buf);    ret = write(fd, buf, strlen(buf));    if(ret < 0)        log_write(ar->c2s->log, LOG_ERR, "pipe: write to pipe failed: %s", strerror(errno));    return ret;}static int _ar_pipe_read(authreg_t ar, int fd, char *buf, int buflen){    int ret;    char *c;    ret = read(fd, buf, buflen);    if(ret == 0)        log_write(ar->c2s->log, LOG_ERR, "pipe: got EOF from pipe");    if(ret < 0)        log_write(ar->c2s->log, LOG_ERR, "pipe: read from pipe failed: %s", strerror(errno));    if(ret <= 0)        return ret;    buf[ret] = '\0';    c = strchr(buf, '\n');    if(c != NULL)        *c = '\0';            log_debug(ZONE, "read from pipe: %s", buf);    return ret;}static int _ar_pipe_user_exists(authreg_t ar, char *username, char *realm){    moddata_t data = (moddata_t) ar->private;    char buf[1024];    if(_ar_pipe_write(ar, data->out, "USER-EXISTS %s %s\n", username, realm) < 0)        return 0;    if(_ar_pipe_read(ar, data->in, buf, 1023) <= 0)        return 0;    if(buf[0] != 'O' || buf[1] != 'K')        return 0;    return 1;}static int _ar_pipe_get_password(authreg_t ar, char *username, char *realm, char password[257]){    moddata_t data = (moddata_t) ar->private;    char buf[1024];    if(_ar_pipe_write(ar, data->out, "GET-PASSWORD %s %s\n", username, realm) < 0)        return 1;    if(_ar_pipe_read(ar, data->in, buf, 1023) <= 0)        return 1;    if(buf[0] != 'O' || buf[1] != 'K')        return 1;    if(buf[2] != ' ' || buf[3] == '\0')    {        log_debug(ZONE, "malformed response from pipe");        return 1;    }    if(ap_base64decode_len(&buf[3], -1) >= 256) {        log_debug(ZONE, "decoded password longer than buffer");        return 1;    }    ap_base64decode(password, &buf[3], -1);    log_debug(ZONE, "got password: %s", password);    return 0;}static int _ar_pipe_check_password(authreg_t ar, char *username, char *realm, char password[257]){    moddata_t data = (moddata_t) ar->private;    char buf[1024];    int plen;    plen = strlen(password);    if(ap_base64encode_len(plen) >= 1023) {        log_debug(ZONE, "unable to encode password");        return 1;    }    ap_base64encode(buf, password, plen);        if(_ar_pipe_write(ar, data->out, "CHECK-PASSWORD %s %s %s\n", username, buf, realm) < 0)        return 1;    if(_ar_pipe_read(ar, data->in, buf, 1023) <= 0)        return 1;    if(buf[0] != 'O' || buf[1] != 'K')        return 1;    return 0;}static int _ar_pipe_set_password(authreg_t ar, char *username, char *realm, char password[257]){    moddata_t data = (moddata_t) ar->private;    char buf[1024];    int plen;    plen = strlen(password);    if(ap_base64encode_len(plen) >= 1023) {        log_debug(ZONE, "unable to encode password");        return 1;    }    ap_base64encode(buf, password, plen);    if(_ar_pipe_write(ar, data->out, "SET-PASSWORD %s %s %s\n", username, buf, realm) < 0)        return 1;    if(_ar_pipe_read(ar, data->in, buf, 1023) <= 0)        return 1;    if(buf[0] != 'O' || buf[1] != 'K')        return 1;    return 0;}static int _ar_pipe_get_zerok(authreg_t ar, char *username, char *realm, char hash[41], char token[11], int *sequence){    moddata_t data = (moddata_t) ar->private;    char buf[1024], *tok, *c;    int i = 0;    if(_ar_pipe_write(ar, data->out, "GET-ZEROK %s %s\n", username, realm) < 0)        return 1;    if(_ar_pipe_read(ar, data->in, buf, 1023) <= 0)        return 1;    if(buf[0] != 'O' || buf[1] != 'K')        return 1;    if(buf[2] != ' ' || !((buf[3] >= '0' && buf[3] <= '9') || (buf[3] >= 'a' && buf[3] <= 'f')))    {        log_debug(ZONE, "malformed response from pipe");        return 1;    }    c = &buf[3];    while(c != NULL && i < 3)    {        tok = c;        c = strchr(c, ' ');        if(c != NULL)        {            *c = '\0';            c++;        }        switch(i)        {            case 0:                snprintf(hash, 41, "%s", tok);                break;            case 1:                snprintf(token, 11, "%s", tok);                break;            case 2:                *sequence = atoi(tok);                break;        }        i++;    }    if(i < 3)    {        log_debug(ZONE, "malformed response from pipe");        return 1;    }    log_debug(ZONE, "got zerok: hash=%s, token=%s, sequence=%d", hash, token, sequence);    return 0;}static int _ar_pipe_set_zerok(authreg_t ar, char *username, char *realm, char hash[41], char token[11], int sequence){    moddata_t data = (moddata_t) ar->private;    char buf[1024];    if(_ar_pipe_write(ar, data->out, "SET-ZEROK %s %s %s %d %s\n", username, hash, token, sequence, realm) < 0)        return 1;    if(_ar_pipe_read(ar, data->in, buf, 1023) <= 0)        return 1;    if(buf[0] != 'O' || buf[1] != 'K')        return 1;    return 0;}static int _ar_pipe_create_user(authreg_t ar, char *username, char *realm){    moddata_t data = (moddata_t) ar->private;    char buf[1024];    if(_ar_pipe_write(ar, data->out, "CREATE-USER %s %s\n", username, realm) < 0)        return 1;    if(_ar_pipe_read(ar, data->in, buf, 1023) <= 0)        return 1;    if(buf[0] != 'O' || buf[1] != 'K')        return 1;    return 0;}static int _ar_pipe_delete_user(authreg_t ar, char *username, char *realm){    moddata_t data = (moddata_t) ar->private;    char buf[1024];    if(_ar_pipe_write(ar, data->out, "DELETE-USER %s %s\n", username, realm) < 0)        return 1;    if(_ar_pipe_read(ar, data->in, buf, 1023) <= 0)        return 1;    if(buf[0] != 'O' || buf[1] != 'K')        return 1;    return 0;}static void _ar_pipe_free(authreg_t ar){    moddata_t data = (moddata_t) ar->private;    if(_ar_pipe_write(ar, data->out, "FREE\n") < 0)        return;    close(data->in);    close(data->out);    free(data);    return;}static void _ar_pipe_signal(int signum){    wait(NULL);    /* !!! attempt to restart the pipe, or shutdown c2s */}/** start me up */int ar_pipe_init(authreg_t ar){    moddata_t data;    int to[2], from[2], ret;    char buf[1024], *tok, *c;    data = (moddata_t) malloc(sizeof(struct moddata_st));    memset(data, 0, sizeof(struct moddata_st));    data->exec = config_get_one(ar->c2s->config, "authreg.pipe.exec", 0);    if(data->exec == NULL)    {        log_write(ar->c2s->log, LOG_ERR, "pipe: no executable specified in config file");        free(data);        return 1;    }    if(pipe(to) < 0)    {        log_write(ar->c2s->log, LOG_ERR, "pipe: failed to create pipe: %s", strerror(errno));        free(data);        return 1;    }    if(pipe(from) < 0)    {        log_write(ar->c2s->log, LOG_ERR, "pipe: failed to create pipe: %s", strerror(errno));        close(to[0]);        close(to[1]);        free(data);        return 1;    }    signal(SIGCHLD, _ar_pipe_signal);    log_debug(ZONE, "attempting to fork");    data->child = fork();    if(data->child < 0)    {        log_write(ar->c2s->log, LOG_ERR, "pipe: failed to fork: %s", strerror(errno));        close(to[0]);        close(to[1]);        close(from[0]);        close(from[1]);        free(data);        return 1;    }    /* child */    if(data->child == 0)    {        log_debug(ZONE, "executing %s", data->exec);        close(STDIN_FILENO);        close(STDOUT_FILENO);        dup2(to[0], STDIN_FILENO);        dup2(from[1], STDOUT_FILENO);        close(to[0]);        close(to[1]);        close(from[0]);        close(from[1]);                execl(data->exec, data->exec, NULL);        log_write(ar->c2s->log, LOG_ERR, "pipe: failed to execute %s: %s", data->exec, strerror(errno));        free(data);        exit(1);    }    log_write(ar->c2s->log, LOG_NOTICE, "pipe authenticator %s running (pid %d)", data->exec, data->child);    /* parent */    close(to[0]);    close(from[1]);    data->in = from[0];    data->out = to[1];    ret = _ar_pipe_read(ar, data->in, buf, 1023);    if(ret <= 0)    {        close(data->in);        close(data->out);        free(data);        return 1;    }    c = buf;    while(c != NULL)    {        tok = c;        c = strchr(c, ' ');        if(c != NULL)        {            *c = '\0';            c++;        }        /* first token must be OK */        if(tok == buf)        {            if(strcmp(tok, "OK") == 0)                continue;            log_write(ar->c2s->log, LOG_ERR, "pipe: pipe authenticator failed to initialise");            kill(data->child, SIGTERM);            close(data->in);            close(data->out);            free(data);            return 1;        }        /* its an option */        log_debug(ZONE, "module feature: %s", tok);        if(strcmp(tok, "USER-EXISTS") == 0)            ar->user_exists = _ar_pipe_user_exists;        else if(strcmp(tok, "GET-PASSWORD") == 0)            ar->get_password = _ar_pipe_get_password;        else if(strcmp(tok, "CHECK-PASSWORD") == 0)            ar->check_password = _ar_pipe_check_password;        else if(strcmp(tok, "SET-PASSWORD") == 0)            ar->set_password = _ar_pipe_set_password;        else if(strcmp(tok, "GET-ZEROK") == 0)            ar->get_zerok = _ar_pipe_get_zerok;        else if(strcmp(tok, "SET-ZEROK") == 0)            ar->set_zerok = _ar_pipe_set_zerok;        else if(strcmp(tok, "CREATE-USER") == 0)            ar->create_user = _ar_pipe_create_user;        else if(strcmp(tok, "DELETE-USER") == 0)            ar->delete_user = _ar_pipe_delete_user;        else if(strcmp(tok, "FREE") == 0)            ar->free = _ar_pipe_free;    }    ar->private = (void *) data;    return 0;}#endif

⌨️ 快捷键说明

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