Ivanovo Linux Users Group -  
Форум Помощь Поиск Вход
Предыдущая Следующая Вверх Тема Администрирование / Работа с сетью / VPN to MySQL (5490 хитов)
- Написал(а) PAHA Дата 14.12.05 11:26
Господа как заставить ВПН сервер при авторизации брать пользователей из базы данных причём в базе будет храниться можно юзера пустить или нельзя
Parent - Написал(а) LOE (Site/forum admin) Дата 14.12.05 12:16
Написать плагин для pppd (на C конечно) и подключить его как дополнительный авторизатор.
plugin filename
       Load  the shared library object file filename as a plugin.  This is a privileged option.
"No! Try not! Do. Or do not. There is no try." -- Yoda
Parent Написал(а) PAHA Дата 14.12.05 13:07
ну и кто у нас силён в Си ? анука признавайтесь :-)
Parent Написал(а) LOE (Site/forum admin) Дата 14.12.05 19:19
Ну что ж.
Даю заготовку плагина AS IS. Дело было давно и многое из памяти стёрлось.

Итак, раскрываем исходники pppd.
Нижеприведенный файл записываем в каталог pppd/plugins с именем pppd-mysql.c
В файле Makefile.linux меняем строку:
PLUGINS := minconn.so passprompt.so passwordfd.so pppd-mysql.so
Подготовить исходники pppd - запустить скрипт configure, потом перейти в каталог pppd/plugins и дать команду make pppd-mysql.so
Должны получить файл pppd-mysql.so

Подключение модуля:
в файле опций pppd прописать:
auth
+pap
plugin /путь/pppd-mysql.so
mysqlserver сервер
mysqluser пользователь
mysqlpass пароль
mysqldb база

Юзаются 2 таблицы:
таблица users с полями user и passwd, хранящими имя пользователя и криптованный(crypt) пароль
таблица block с полями user и block, хранящими имя пользователя и 1(единичку) - если юзер заблокирован
Внимание! Используется PAP авторизация!

Исходник pppd-mysql.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <stddef.h>
#include "pppd.h"

char pppd_version[] = VERSION;

#include "mysql/mysql.h"

MYSQL mysql;

#define QBUF_LEN  512
char qbuf[QBUF_LEN];
char *mqbuf;
int qbufleft;
int slen;
MYSQL_RES *result;
MYSQL_ROW row;
unsigned long *lengths;
char salt[3];
char crypted_pw[36];
char *xpasswd;
int rez;

static void lfree_wordlist __P((struct wordlist *));

#define MYSTRCAT(STRING) do { strncpy(mqbuf, STRING, qbufleft);          \
                        slen = strlen(STRING);                     \
                  qbufleft -= slen;                          \
                   mqbuf += slen; } while(0)
#define MYSTRCATESC(STRING) do {                                         \
       slen = strlen(STRING);                                            \
       slen = mysql_escape_string(mqbuf, STRING,                         \
       (qbufleft/2 < slen ? qbufleft/2 : slen));                  \
       mqbuf += slen;                                                   \
       qbufleft -= slen;                                                \
     } while(0)
#define MYSTRCATCHR(C)  do {                                             \
                            if(qbufleft>0) {                            \
                            *mqbuf++=C;                             \
                            *mqbuf = '\0';                          \
                            qbufleft--;                             \
                             }                                          \
                            } while(0)

static char mysqlserver[PATH_MAX+1];
static char mysqluser[PATH_MAX+1];
static char mysqlpass[PATH_MAX+1];
static char mysqldb[PATH_MAX+1];

static option_t my_options[] = {
  { "mysqlserver", o_string, mysqlserver,
    "MySQL server",
    OPT_STATIC, NULL, PATH_MAX },
  { "mysqluser", o_string, mysqluser,
    "MYSQL user",
    OPT_STATIC, NULL, PATH_MAX },
  { "mysqlpass", o_string, mysqlpass,
    "MYSQL password",
    OPT_STATIC, NULL, PATH_MAX },
  { "mysqldb", o_string, mysqldb,
    "MYSQL database",
    OPT_STATIC, NULL, PATH_MAX },
  { NULL }
};

static int my_mysql( char *user, char *passwd, char **msgp,
                     struct wordlist **addrs,
                     struct wordlist **opts)
{
  struct wordlist *ap, *addr_list, *alist, **app;
  char *dev;
  if (addrs != NULL)
          *addrs = NULL;
  if (opts != NULL)
          *opts = NULL;
      addr_list = NULL;
  rez=1;
  dbglog("Connecting to %s %s %s %s", mysqlserver,mysqldb,mysqluser,mysqlpass);
  dev = devnam;
  if (strncmp(dev, "/dev/", 5) == 0)
    dev += 5;
//dbglog("TTY=%s",dev);
  if(!(mysql_init(&mysql))) {
    dbglog("MySQL initoalization failed");
    return(-1);
  }
//    exiterr(mysql_errno(&mysql));

  if(!(mysql_real_connect(&mysql,mysqlserver,mysqluser,mysqlpass,mysqldb,0,NULL,0))) {
//    dbglog("MySQL connection to host %s:%s %s:%s failed",mysqlserver,mysqldb,mysqluser,mysqlpass);
    return(-1);
  }
//    exiterr(mysql_errno(&mysql));

  mqbuf = qbuf;
  qbufleft = QBUF_LEN-1;
  MYSTRCAT("SELECT ");
  MYSTRCAT("passwd FROM users WHERE user='");
  MYSTRCATESC(user);
  MYSTRCATCHR('\'');

  if (mysql_query(&mysql,(char *)qbuf) < 0) {
//    fprintf(stderr,"%s : %s\n",mysql_error(&mysql),qbuf);
    dbglog("MySQL query %s failed (%s)",qbuf,mysql_error(&mysql));
    mysql_close(&mysql);
    return(-1);
  }
  if(!(result = mysql_use_result(&mysql))) {
    dbglog("MySQL query result failed");
    mysql_close(&mysql);
//    fprintf(stderr,"Query result failed\n");
    return(-1);
  }
  if(!(row = mysql_fetch_row(result))) {
    mysql_free_result(result);
    mysql_close(&mysql);
//    fprintf(stderr,"Fetch result failed\n");
    dbglog("MySQL fetch row failed");
    return(-1);
  }
  lengths = mysql_fetch_lengths(result);
//  strcpy(crypted_pw, crypt(passwd, row[0]));
  xpasswd = crypt(passwd, row[0]);
  if (strcmp(row[0],xpasswd)) {
    mysql_free_result(result);
    mysql_close(&mysql);
//    fprintf(stderr,"Password incorrect\n");
//    dbglog("Password for user incorrect");
    return(0);
  }
  mysql_free_result(result);

  mqbuf = qbuf;
  qbufleft = QBUF_LEN-1;
  MYSTRCAT("SELECT ");
  MYSTRCAT("block FROM block WHERE user='");
  MYSTRCATESC(user);
  MYSTRCATCHR('\'');
  if (mysql_query(&mysql,(char *)qbuf) < 0) {
//    fprintf(stderr,"%s : %s\n",mysql_error(&mysql),qbuf);
    mysql_close(&mysql);
//    exit(1);
    return(-1);
  }
  if(!(result = mysql_use_result(&mysql))) {
    mysql_close(&mysql);
//    fprintf(stderr,"Query result failed\n");
//    exit(1);
    return(-1);
  }
  if(!(row = mysql_fetch_row(result))) {
    rez=0;
  }
  mysql_free_result(result);
  mysql_close(&mysql);

  if (rez) {
    app = &alist;
    ap = (struct wordlist *)
      malloc(sizeof(struct wordlist) + strlen("4.3.2.1") + 1);
    if (ap == NULL)
      novm("authorized addresses");
    ap->word = (char *) (ap + 1);
    strcpy(ap->word, "4.3.2.1");
    *app = ap;
    app = &ap->next;
    *app = NULL;
    if (addr_list)
      lfree_wordlist(addr_list);
    addr_list = alist;
    if (addrs != NULL)
      *addrs = addr_list;
    else if (addr_list != NULL)
      lfree_wordlist(addr_list);
  }

  return(rez);
}

void plugin_init(void)
{
//  info("mysql plugin init");
  add_options(my_options);
  pap_auth_hook=my_mysql;
}

static void
lfree_wordlist(wp)
    struct wordlist *wp;
{                      
    struct wordlist *next;

    while (wp != NULL) {
        next = wp->next;
        free(wp);
        wp = next;
    }
}


Внимание!!! Это - только заготовка. В программе есть недоработки!
Лично я использую более другую версию плагина, который проверяет условия подключения не напрямую, а косвенно через вспомогательную программу (у меня намного больше проверок, а не только имя-пароль-блокировка)

Еще недостаток - явно прописан выдаваемый юзеру ИП 4.3.2.1 :-)
Честно говоря, готовил именно этот исходник давно и цель была исследовательская.

Если кто доработает и предоставит общественности, думаю, найдется кто скажет спасибо.
(вполне возможно, сразу плагин и не заработает, пробовать сейчас негде)
"No! Try not! Do. Or do not. There is no try." -- Yoda
Предыдущая Следующая Вверх Тема Администрирование / Работа с сетью / VPN to MySQL (5490 хитов)

Powered by mwForum 2.12.0 © 1999-2007 Markus Wichitill

Page created in 0.081s with 10 database queries.