Chinaunix

标题: 请问能实现vsftp+pam+oracle9i吗? [打印本页]

作者: freechan    时间: 2004-03-23 21:31
标题: 请问能实现vsftp+pam+oracle9i吗?
导师叫我用vsftp+pam+oracle9i的方式进行ftp用户认证,但看了前面proftp+oracle9i的帖子,感觉没什么希望了。
    我们的最初设想是这样的:同时要上个网站和ftp server.网站要用到oracle9i的数据库。ftp server 用vsftp,大概要建200个左右的ftp用户,每个用户要有自己的用户名和密码,而且能够通过网站来修改ftp用户的密码。这样大概就要用vsftp+pam+数据库文件的模式。导师想把两个数据库统一起来,就说统一用oracle了。请过往的牛人根据我们的设想指点一二,看有个什么好点的解决方案,真的谢谢了!!!
作者: 好好先生    时间: 2004-03-23 21:37
标题: 请问能实现vsftp+pam+oracle9i吗?
可以参看别人用mysql+proftp的贴子,其实方法应该是差不太多,后台用什么数据库影响不大吧?只是oracle曲高和寡,用的人少一点罢了。
作者: freechan    时间: 2004-03-24 19:46
标题: 请问能实现vsftp+pam+oracle9i吗?
是这样的,vsftp可以用mysql,在于有人做了个pam_mysql的插件,所以pam可以用mysql做后台,但是我没有发现针对oracle的pam插件,所以感觉不好做。
作者: 好好先生    时间: 2004-03-24 19:56
标题: 请问能实现vsftp+pam+oracle9i吗?
首先声明我不是很懂编程。
我想可不可以这样,把pam_mysql反编译,然后参考它写一个pam_oracle。那么剩下的问题就好解决了吧?
作者: 好好先生    时间: 2004-03-24 20:00
标题: 请问能实现vsftp+pam+oracle9i吗?
其实我看/etc/pam.d/ftp和ftp.vu都是文本的语句,是调用的其它的限制模块。我想pam_mysql也类似吧,可不可以把你看到的pam_mysql让我看一下?
作者: 好好先生    时间: 2004-03-24 20:15
标题: 请问能实现vsftp+pam+oracle9i吗?
我看了,难的是做一个pam_oracle.so文件。
作者: 好好先生    时间: 2004-03-24 20:28
标题: 请问能实现vsftp+pam+oracle9i吗?
参考这个写一个for linux的pam_oracle吧。
----Oracle кусок----
oracle_connector.c
----Oracle кусок----

#define _GNU_SOURCE

#include <stdio.h>;
#include <stdlib.h>;
#include <unistd.h>;
#include <syslog.h>;
#include <stdarg.h>;
#include <alloca.h>;
#include <string.h>;

#include <sys/types.h>;
#include <sys/socket.h>;
#include <netinet/in.h>;
#include <netdb.h>;

#include <sqlora.h>;

#define DEBUG
#define ERR -1
#define SUCCESS 1
#define BUFSZ 128

struct optionstruct {
    char where[257];
    char connectString[65];
    char table[30];
    char usercolumn[17];
    char passwdcolumn[30];

};

struct optionstruct options = {
    "uss_sl_type='MAIL'",
    "user/password@servername",
    "abs.ct_user_services",
    "uss_logname",
    "uss_password"
};

/* Global Variables */
int dbh = -1;

int db_connect (void);
void db_close( void );

void db_close ( void )
{
        if (dbh < 0)
        {
                return; /* closed already ? */
        }
        sqlo_finish(dbh);
        dbh = -1;
}

int db_connect ( void )
{
        int retvalue = ERR;
        char* conn_string;
        int conn_count;
        retvalue = -1;
        if ( dbh >;= 0 )
                return SUCCESS;
        sqlo_init(0);
        if (0 <= (dbh = sqlo_connect(&dbh, options.connectString)))
        {
                retvalue = SUCCESS;
        }
        if ( retvalue != SUCCESS )
        {
                syslog(LOG_INFO, "oracle_connector: Oracle err %s\n", sqlo_geterror(dbh));
        }
        return retvalue;
}


char *db_getpasswd (const char *user)
{
        char *p;
        char *sql;
        char *escapeUser;       // User provided stuff MUST be escaped
        int ncount;
        const char *retvalue = NULL;
        int sth;
        const char **v;

        sql = (char *) malloc (110 + strlen(user) + strlen(options.where));
        if ( !sql )
                return "ERR";

        escapeUser = malloc(sizeof(char) * (strlen(user) * 2) + 1);
        if ( escapeUser == NULL )
        {
                syslog(LOG_ERR, "oracle_connector: Insufficient memory to allocate user or password escape strings";
                syslog(LOG_ERR, "oracle_connector: UNABLE TO AUTHENTICATE";
                return "ERR";
        }
        escapeUser = (char*) user;
//      D (("options.crypt=%d|\n", options.crypt));


        sprintf(sql, "select %s from %s where %s='%s' ",
                options.passwdcolumn,options.table,
                options.usercolumn,escapeUser,escapeUser);
        if ( strlen(options.where) >; 0 )
        {
                sprintf(sql, "%s and %s", sql, options.where);
        }

        printf("%s\n",sql);

        //ncount = sqlo_run(dbh, sql, 0 , NULL);

        //if (sth == SQLO_ERROR)
        if (0>; (sth = sqlo_open(dbh, sql, 0, NULL)))
        {
                syslog(LOG_ERR, sqlo_geterror (dbh));
                syslog(LOG_ERR, "Help1 hoi=%s|\n", sqlo_geterror(dbh));
                return "ERR";
        }
        while (0==sqlo_fetch(sth,1)) {
            v=sqlo_values(sth,NULL,0);
            p=v[0];
            //return "%s",v[0];
            return p;
        }

        if (0 != sqlo_close(sth)) {
            printf("select failed to close cursor: %s\n",sqlo_geterror(dbh));
            return "ERR";
        }
}


int main() {
int ret;
char *pass;
char *pw;
char key[2];

int s, c, sz,i;
struct sockaddr_in ssa, csa;
struct sockaddr *sp, *cp;
struct hostent *rhost;
char *host, *tstr;
char buf[BUFSZ];
char *userget;
char username;
const char sss;
time_t itime;

sp=(struct sockaddr *)&amp;
cp=(struct sockaddr *)&amp;
sz=sizeof(ssa);

// Создаём сокет
s=socket(AF_INET, SOCK_STREAM, 0);
if(s == -1){
        perror("Невозможно создать сокет";
        exit(1);
}

// Резервируем порт 1500
ssa.sin_family = AF_INET;
ssa.sin_port = htons(1500);
ssa.sin_addr.s_addr = INADDR_ANY;

if(bind(s, sp, sz) == -1){
        perror("Невозможно занять порт";
        exit(1);
}
// Переводим сокет в режим ожидания соединения
if(listen(s, 0) == -1){
        perror("Невозможно перейти в режим ожидания";
        exit(1);
}

//Установим соединение с ораклом
ret=db_connect();
printf("Oracle Connected: %d\n",ret);

while(1){
        write(1,"i'm here\n",10);
        // Принимаем соединение
        if((c = accept(s, cp, &sz)) == -1) {
                perror("Ошибка при выполнении accept";
                exit(1);
        }

        //Получим от клиента имя пользователя
        while((i=recv(c,buf,BUFSZ,0)) >; 0) {
            //write(1,buf,i);
            userget = (char*)malloc((i)*sizeof(char));
            strncpy(userget,buf,i);
            userget='\0';

            break;
        }

        // Преобразуем адрес хоста отправителя в его имя
        rhost=gethostbyaddr((char*)(&csa.sin_addr),
        sizeof(csa.sin_addr), AF_INET);
        if(h_errno){
                printf("gethostbyaddr error: %d\n", h_errno);
                host=inet_ntoa(csa.sin_addr);
        } else {
                host=rhost->;h_name;
        }

        // Получаем строку, содержащую дату и время
        if((itime = time(NULL)) < 0){
                perror("Не удалось получить время";
                exit(1);
        }
        tstr = ctime(&itime);
        // Выводим время поступления запроса,
        // адрес и порт отправителя
        printf("%s request from %s:%d, user name %s\n", tstr, host, htons(csa.sin_port),userget);

        pass =(char*)malloc(30*sizeof(char));
        pass =NULL;

        pass = db_getpasswd(userget);
        if (pass != NULL) {
          pass[strlen(pass)]='\0';
          printf("assword for user %s is %s\n",userget,pass);
          send(c, pass, strlen(pass), 0);
        }
        else
        {
          send(c, "error", 5, 0);
        }
        free(userget);
        free(pass);

        // Закрываем соединение
        close(c);
}

close(c);
close(s);
db_close();

return 1;
}

---------------------========================---------------------
Компилирую так
rm oracle_connector
gcc -o oracle_connector oracle_connector.c -lsqlora8 -lcrypt
---------------------========================---------------------
---------------------========================---------------------
---------------------========================---------------------
Вот кусок который pam модуль
---------------------========================---------------------
#include <security/pam_modules.h>;
#include <stdarg.h>;
#include <time.h>;
#include <pwd.h>;
#include <security/pam_misc.h>;

#include <stdio.h>;
#include <sys/types.h>;
#include <sys/socket.h>;
#include <netinet/in.h>;

//Это определит тип нашего модуля
#define PAM_SM_AUTH
#define BUFSZ 128
#define MAX_V 30
#define LOG_DEBUG 1
#define PLEASE_ENTER_PASSWORD "assword:"

int converse (pam_handle_t * pamh, int nargs, struct pam_message **message, struct pam_response **response);

int askForPassword(pam_handle_t *pamh);

int askForPassword(pam_handle_t *pamh)
{
     struct pam_message msg[1], *mesg[1];
struct pam_response *resp=NULL;
char *prompt=NULL;
int i=0;
int retval;
prompt = malloc(strlen(PLEASE_ENTER_PASSWORD));
if (prompt == NULL)
{
syslog(LOG_DEBUG,"pam_test: askForPassword(), out of memory!?";
return PAM_BUF_ERR;
}
else
{
sprintf(prompt,PLEASE_ENTER_PASSWORD);
msg.msg = prompt;
}
msg.msg_style = PAM_PROMPT_ECHO_OFF;
mesg = &msg;

retval = converse(pamh, ++i, mesg, &resp);
if (retval != PAM_SUCCESS) {
return retval;
}
return pam_set_item(pamh, PAM_AUTHTOK, resp->;resp);
}

int converse(pam_handle_t *pamh, int nargs
, struct pam_message **message
, struct pam_response **response)
{
int retval;
struct pam_conv *conv;

retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv );
if (retval == PAM_SUCCESS)
{
retval = conv->;conv(nargs, (const struct pam_message **) message
, response, conv->;appdata_ptr);
if ((retval != PAM_SUCCESS)) // && (retval != PAM_CONV_AGAIN)
{
syslog(LOG_DEBUG, "pam_test: conversation failure [%s]"
, pam_strerror(pamh, retval));
}
}
else
{
syslog(LOG_DEBUG, "pam_test: couldn't obtain conversation function [%s]"
, pam_strerror(pamh, retval));
}
return retval;
}

PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags
                                   ,int argc, const char **argv)
{
        int retval;
        const char *user;
char *passwd = NULL;

        int s, sz, i;
        struct sockaddr_in ssa;
        struct sockaddr *sp;
        struct in_addr sip;
        char buf[BUFSZ];
char *str;
char key[2];
char *pw;


        sp=(struct sockaddr *)&amp;
        sz=sizeof(ssa);

        if(argc!=1){
                // Помощь по использованию команды
                printf("Использование: pam_модуль.so ip-адрес\n";
                exit(1);
        }
        if(inet_aton(argv[0], &sip) != 1){
                printf("Неправильно задан адрес сервера\n";
                exit(1);
        }

syslog(1,"!!!!!!!!!!!!!!!!!!-----1-----!!!!!!!!!!!!!!!!!!!!!");
        retval = pam_get_user(pamh, &user, NULL);
if (retval != PAM_SUCCESS || user == NULL) {
syslog(LOG_DEBUG, "pam_test: no user specified");
return PAM_USER_UNKNOWN;
}
syslog(1,"!!!!!!!!!!!!!!!!!!-----2-----!!!!!!!!!!!!!!!!!!!!!");
retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &passwd);
if (passwd == NULL) {
askForPassword(pamh);
}
retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &passwd);
syslog(1,"!!!!!!!!!!!!!!!!!!-----3-----!!!!!!!!!!!!!!!!!!!!!");
if (passwd == NULL)
return PAM_AUTHINFO_UNAVAIL;

const char *host;
int pam_err;
pam_err = pam_get_item(pamh, PAM_RHOST, (const void **) &host);
if (host==NULL) {
host="localhost";
}
syslog(LOG_DEBUG,"pam_test: HOST: %s",host);
syslog(LOG_DEBUG,"pam_test: USER: %s",user);
syslog(LOG_DEBUG,"pam_test: PASS: %s",passwd);

        // Создаём сокет
        s=socket(AF_INET, SOCK_STREAM, 0);
        if(s == -1){
                perror("Невозможно создать сокет");
                exit(1);
        }

// Задаём адрес сервера
        ssa.sin_family = AF_INET;
        ssa.sin_port = htons(1500);
        ssa.sin_addr = sip;

// Устанавливаем соединение
        if(connect(s, sp, sz) == -1){
                perror("Не удалось установить соединение");
                exit(1);
        }
// Посылаем login на сервер
str = user;
        send(s,str,strlen(str),0);


// Получаем данные от сервера
        while((i=recv(s, buf, BUFSZ, 0)) >; 0) {
//pw = (char*)malloc(i*sizeof(char));
pw = (char*)malloc(13*sizeof(char));
//strncpy(pw,buf,i);
strncpy(pw,buf,13);
//pw[strlen(pw)]='\0';
pw[13]='\0';
}
strncpy(key,pw,2);
key[2] = '\0';
syslog(1,"key is %s",key);
char *cryptpass;
cryptpass = (char*)malloc(i*sizeof(char));
cryptpass=crypt(passwd,key);
cryptpass[strlen(cryptpass)]='\0';
syslog(1,"%s, %s, %d, %d",pw,cryptpass,strlen(pw),strlen(cryptpass));
retval = PAM_BUF_ERR;
if (!strcmp(pw,cryptpass)) {
  syslog(1,"ПАРОЛИ СОВПАДАЮТ");
  retval = PAM_SUCCESS;
}
else{
  syslog(1,"ПАРОЛИ РАЗНЫЕ");
}
free(pw);
//free(cryptpass);
return retval;
}


PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags
                              ,int argc, const char **argv)
{
        unsigned int ctrl;
        int retval;


        retval = PAM_SUCCESS;
        return retval;
}

// Это определение необходимо для статической линковки модулей PAM в приложениях.
#ifdef PAM_STATIC
struct pam_module _pam_unix_auth_modstruct = {
    "pam_test",
    pam_sm_authenticate,
    pam_sm_setcred,
    NULL,
    NULL,
    NULL,
    NULL,
};
#endif

--------------------========================---------------------
Компилирую так:
rm *.o
rm *.so
gcc -fPIC -c pam_test.c
gcc -shared -o pam_test.so pam_test.o -lcrypt
cp pam_test.so /usr/lib/pam_test.so
--------------------========================---------------------
Далее, в /etc/pam.d/pop3
auth required pam_test.so XX.XX.XX.XX
где XX.XX.XX.XX - это ip адрес сервера с oracle

原文出处:http://www3.opennet.ru/openforum/vsluhforumID9/1913.html
作者: freechan    时间: 2004-03-25 13:09
标题: 请问能实现vsftp+pam+oracle9i吗?
好好先生你真是太好了,太强了,我试试你给的东东。
非常感谢!!!




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2