
Ну что ж.
Даю заготовку плагина
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