From bcb6bf25fa132421672d0782b9bfdb82fd2c6600 Mon Sep 17 00:00:00 2001 From: Aris Adamantiadis Date: Mon, 29 Aug 2005 14:29:07 +0000 Subject: the server now does the chroot and change uid. There is also an option "nopassword" for ftp users. git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@25 7dcaeef0-15fb-0310-b436-a5af3365683c --- sftp_server/config.c | 52 +++++++++++++++++++++++++++++++ sftp_server/main.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++--- sftp_server/server.h | 4 +++ sftp_server/sftp.conf | 1 + 4 files changed, 136 insertions(+), 5 deletions(-) diff --git a/sftp_server/config.c b/sftp_server/config.c index be69d077..3dc2bc6f 100644 --- a/sftp_server/config.c +++ b/sftp_server/config.c @@ -136,6 +136,8 @@ int group_callback(const char *shortvar, const char *var, const char *arguments, if(!strcasecmp(shortvar,"chroot")){ current_group->chroot=strdup(value); } + if(!strcasecmp(shortvar,"nopassword")) + current_group->nopassword=1; } return LC_CBRET_OKAY; } @@ -278,6 +280,7 @@ int parse_config(char *file){ r=lc_register_callback("group.uid",0,LC_VAR_UNKNOWN,group_callback,NULL); r=lc_register_callback("group.chroot",0,LC_VAR_UNKNOWN,group_callback,NULL); r=lc_register_callback("group.group",0,LC_VAR_UNKNOWN,group_callback,NULL); + r=lc_register_callback("group.nopassword",0,LC_VAR_NONE,group_callback,NULL); // lc_register_var("dir", LC_VAR_SECTION, NULL, 0); r=lc_register_callback("dir",0,LC_VAR_NONE,dir_callback,NULL); r=lc_register_callback("dir.list",0,LC_VAR_UNKNOWN,dir_callback,NULL); @@ -291,3 +294,52 @@ int parse_config(char *file){ list_config(); return 0; } + +list *find_groups(char *user){ + return list_find(users,user); +} + +char *user_chroot(char *user){ + char *c_grp; + list *group=find_groups(user); + struct group *grp; + while(group){ + c_grp=group->key; + grp=list_find(groups,c_grp); + if(grp->chroot) + return grp->chroot; + group=group->next; + } + return NULL; +} + +char *user_uid(char *user){ + char *c_grp; + list *group=find_groups(user); + struct group *grp; + while(group){ + c_grp=group->key; + grp=list_find(groups,c_grp); + if(grp->uid) + return grp->uid; + group=group->next; + } + return NULL; +} + +/* 0 if it's not specified. 1 if the user doesn't need a password */ +int user_nopassword(char *user){ + char *c_grp; + list *group=find_groups(user); + struct group *grp; + if(!group) + return 0; //user doesn't exist + while(group){ + c_grp=group->key; + grp=list_find(groups,c_grp); + if(grp->nopassword) + return 1; + group=group->next; + } + return 0; +} diff --git a/sftp_server/main.c b/sftp_server/main.c index 7b276d2e..949b9979 100644 --- a/sftp_server/main.c +++ b/sftp_server/main.c @@ -35,6 +35,7 @@ MA 02111-1307, USA. */ #include #include #include +#include #include "server.h" @@ -81,7 +82,59 @@ int password_conv(int num_msg, const struct pam_message **msg, return PAM_SUCCESS; } - +/* postauth_conf returns -1 on error, else 0 */ +int postauth_conf(char *user){ + /* first, find a chroot if any */ + char *root,*ptr; + char *char_uid; + char buffer[256]; + int uid; + struct passwd *pw=getpwnam(user); + root=user_chroot(user); + if(root){ + if((ptr=strstr(root,"$HOME"))){ + if(!pw) + return -1; // this user has no user directory + *ptr=0; + snprintf(buffer,sizeof(buffer),"%s%s/%s", + root,pw->pw_dir,ptr+strlen("$HOME")); + } + else + snprintf(buffer,sizeof(buffer),"%s",root); + } + /* we don't chroot right now because we still need getpwnam() */ + char_uid=user_uid(user); + if(!char_uid){ + if(!pw) + return -1; // user doesn't exist ! + char_uid=user; + } + uid=atoi(char_uid); + if(uid==0 && char_uid[0]!=0){ + pw=getpwnam(char_uid); + if(!pw) + return -1; + uid=pw->pw_uid; + } + if(root && chroot(buffer)){ + return -1; // cannot chroot + } + if(root){ + chdir("/"); + } else { + if(pw) + chdir(pw->pw_dir); + else + chdir("/"); + } + if(setuid(uid)){ + return -1; // cannot setuid + } + return 0; +} + + + struct pam_conv pam_conv ={ password_conv, NULL }; /* returns 1 if authenticated, 0 if failed, -1 if you must leave */ @@ -101,6 +154,8 @@ int auth_password(char *user, char *password){ memset(password,0,strlen(password)); if(ret==PAM_SUCCESS){ pam_end(pamh,PAM_SUCCESS); + if(postauth_conf(user)) + return -1; return 1; } else { pam_end(pamh,PAM_AUTH_ERR); @@ -469,13 +524,32 @@ int do_auth(SSH_SESSION *session){ ssh_say(1,"Auth refused\n"); break; } - if(auth==1) + if(auth==1){ break; + } else { + ssh_message_auth_set_methods(message,SSH_AUTH_PASSWORD); + ssh_message_reply_default(message); + } + break; // not authenticated, send default message case SSH_AUTH_NONE: - //ssh_message_auth_reply_success(message,0); - //auth=1; - //break; + if(user_nopassword(ssh_message_auth_user(message))){ + if(postauth_conf(ssh_message_auth_user(message))==0){ + ssh_message_auth_reply_success(message,0); + auth=1; + ssh_say(1,"Authentication success for %s(no password)\n", + ssh_message_auth_user(message)); + break; + } else { + ssh_say(1,"Post-auth failed\n"); + ssh_message_auth_set_methods(message,SSH_AUTH_PASSWORD); + ssh_message_reply_default(message); + } + } else { + ssh_message_auth_set_methods(message,SSH_AUTH_PASSWORD); + ssh_message_reply_default(message); + } + break; default: ssh_message_auth_set_methods(message,SSH_AUTH_PASSWORD); ssh_message_reply_default(message); diff --git a/sftp_server/server.h b/sftp_server/server.h index 866eb70c..1457e81f 100644 --- a/sftp_server/server.h +++ b/sftp_server/server.h @@ -1,6 +1,9 @@ /* server.h */ /* headers for the sftp server project */ int parse_config(char *file); +char *user_chroot(char *user); +char *user_uid(char *user); +int user_nopassword(char *user); typedef struct list_struct { struct list_struct *next; @@ -17,6 +20,7 @@ struct group { char *chroot; char *uid; char *gid; + int nopassword; }; struct dir { diff --git a/sftp_server/sftp.conf b/sftp_server/sftp.conf index f17aae83..842c91c9 100644 --- a/sftp_server/sftp.conf +++ b/sftp_server/sftp.conf @@ -8,6 +8,7 @@ Hostkeydsa /etc/ssh/ssh_host_dsa_key user ftp, anonymous, anon uid ftp + nopassword chroot /home/ftp -- cgit v1.2.3