diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2005-08-26 00:26:18 +0000 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2005-08-26 00:26:18 +0000 |
commit | 7812915daa1bdb3198059f97e0fb889f0b39b7d2 (patch) | |
tree | 33710144ac6ae32e1d3e8b6597b5f7203490d7c0 | |
parent | e2bdc2f66c85d4d1a38b2511cb98da105cafcc24 (diff) | |
download | libssh-7812915daa1bdb3198059f97e0fb889f0b39b7d2.tar.gz libssh-7812915daa1bdb3198059f97e0fb889f0b39b7d2.tar.xz libssh-7812915daa1bdb3198059f97e0fb889f0b39b7d2.zip |
I've forgot about sftp_server/ :)
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@17 7dcaeef0-15fb-0310-b436-a5af3365683c
-rw-r--r-- | sftp_server/Makefile | 37 | ||||
-rw-r--r-- | sftp_server/Makefile.in | 37 | ||||
-rw-r--r-- | sftp_server/main.c | 333 |
3 files changed, 407 insertions, 0 deletions
diff --git a/sftp_server/Makefile b/sftp_server/Makefile new file mode 100644 index 00000000..ca0a1b1c --- /dev/null +++ b/sftp_server/Makefile @@ -0,0 +1,37 @@ + +OBJECTS= main.o +SHELL = /bin/sh + + +subdirs = @subdirs@ +top_srcdir = .. +srcdir = . +prefix = /usr/local +exec_prefix = ${prefix} +bindir = $(exec_prefix)/bin +incldir= $(prefix)/include +infodir = $(prefix)/info +libdir = $(prefix)/lib/ +mandir = $(prefix)/man/man1 + +CC = gcc +CFLAGS = -g -O2 -Wall -g -I../include/ +LDFLAGS = -L../libssh/ -lssh +LIBS = -lz -lcrypto +INSTALL = /usr/bin/install -c +DYLIB_EXTENSION = so +LIBSSH_LDFLAGS = -shared + +all: sftp_server + +sftp_server: $(OBJECTS) ../libssh/libssh.$(DYLIB_EXTENSION) + $(CC) -o sftp_server $(OBJECTS) $(LIBS) $(LDFLAGS) +install: all + $(top_srcdir)/mkinstalldirs $(incldir) + $(top_srcdir)/mkinstalldirs $(libdir) + $(INSTALL) sftp_server $(bindir) +clean: + rm -f *~ sftp_server *.o +distclean: clean + rm -f Makefile + diff --git a/sftp_server/Makefile.in b/sftp_server/Makefile.in new file mode 100644 index 00000000..8a261f18 --- /dev/null +++ b/sftp_server/Makefile.in @@ -0,0 +1,37 @@ + +OBJECTS= main.o +SHELL = /bin/sh +VPATH = @srcdir@ + +subdirs = @subdirs@ +top_srcdir = @top_srcdir@ +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = $(exec_prefix)/bin +incldir= $(prefix)/include +infodir = $(prefix)/info +libdir = $(prefix)/lib/ +mandir = $(prefix)/man/man1 + +CC = @CC@ +CFLAGS = @CFLAGS@ -Wall -g -I../include/ +LDFLAGS = -L../libssh/ -lssh +LIBS = @LIBS@ +INSTALL = @INSTALL@ +DYLIB_EXTENSION = @DYLIB_EXTENSION@ +LIBSSH_LDFLAGS = @LIBSSH_LDFLAGS@ + +all: sftp_server + +sftp_server: $(OBJECTS) ../libssh/libssh.$(DYLIB_EXTENSION) + $(CC) -o sftp_server $(OBJECTS) $(LIBS) $(LDFLAGS) +install: all + $(top_srcdir)/mkinstalldirs $(incldir) + $(top_srcdir)/mkinstalldirs $(libdir) + $(INSTALL) sftp_server $(bindir) +clean: + rm -f *~ sftp_server *.o +distclean: clean + rm -f Makefile + diff --git a/sftp_server/main.c b/sftp_server/main.c new file mode 100644 index 00000000..b829080e --- /dev/null +++ b/sftp_server/main.c @@ -0,0 +1,333 @@ +/* sshd.c */ +/* yet another ssh daemon (Yawn!) */ +/* +Copyright 2004 Aris Adamantiadis + +This file is part of the SSH Library + +The SSH Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The SSH Library 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the SSH Library; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <libssh/libssh.h> +#include <libssh/server.h> +#include <libssh/sftp.h> +#include <unistd.h> +#include <string.h> +#include <limits.h> +#include <dirent.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> + +#define TYPE_DIR 1 +#define TYPE_FILE 1 +struct sftp_handle { + int type; + int offset; + char *name; + int eof; + DIR *dir; + FILE *file; +}; + +int auth_password(char *user, char *password){ + if(strcmp(user,"aris")) + return 0; + if(strcmp(password,"lala")) + return 0; + return 1; // authenticated +} + +int reply_status(SFTP_CLIENT_MESSAGE *msg){ + switch(errno){ + case EACCES: + return sftp_reply_status(msg,SSH_FX_PERMISSION_DENIED, + "permission denied"); + case ENOENT: + return sftp_reply_status(msg,SSH_FX_NO_SUCH_FILE, + "no such file or directory"); + case ENOTDIR: + return sftp_reply_status(msg,SSH_FX_FAILURE, + "not a directory"); + default: + return sftp_reply_status(msg,SSH_FX_FAILURE,NULL); + } +} + +void handle_opendir(SFTP_CLIENT_MESSAGE *msg){ + DIR *dir=opendir(msg->filename); + struct sftp_handle *hdl; + STRING *handle; + if(!dir){ + reply_status(msg); + return; + } + hdl=malloc(sizeof(struct sftp_handle)); + memset(hdl,0,sizeof(struct sftp_handle)); + hdl->type=TYPE_DIR; + hdl->offset=0; + hdl->dir=dir; + hdl->name=strdup(msg->filename); + handle=sftp_handle_alloc(msg->sftp,hdl); + sftp_reply_handle(msg,handle); + free(handle); +} + +SFTP_ATTRIBUTES *attr_from_stat(struct stat *statbuf){ + SFTP_ATTRIBUTES *attr=malloc(sizeof(SFTP_ATTRIBUTES)); + memset(attr,0,sizeof(*attr)); + attr->size=statbuf->st_size; + attr->uid=statbuf->st_uid; + attr->gid=statbuf->st_gid; + attr->permissions=statbuf->st_mode; + attr->atime=statbuf->st_atime; + attr->mtime=statbuf->st_mtime; + attr->flags=SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_UIDGID + | SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME; + return attr; +} + +int handle_lstat(SFTP_CLIENT_MESSAGE *msg){ + struct stat statbuf; + SFTP_ATTRIBUTES *attr; + if(lstat(msg->filename,&statbuf)){ + reply_status(msg); + return 0; + } + attr=attr_from_stat(&statbuf); + sftp_reply_attr(msg, attr); + sftp_attributes_free(attr); + return 0; +} + +int handle_readdir(SFTP_CLIENT_MESSAGE *msg){ + struct sftp_handle *handle=sftp_handle(msg->sftp,msg->handle); + SFTP_ATTRIBUTES *attr; + struct dirent *dir; + struct stat statbuf; + char file[1024]; + int i; + if(!handle || handle->type!=TYPE_DIR){ + sftp_reply_status(msg,SSH_FX_BAD_MESSAGE,"invalid handle"); + return 0; + } + for(i=0; !handle->eof && i<10;++i){ + dir=readdir(handle->dir); + if(!dir){ + handle->eof=1; + break; + } + snprintf(file,sizeof(file),"%s/%s",handle->name, + dir->d_name); + if(lstat(file,&statbuf)){ + memset(&statbuf,0,sizeof(statbuf)); + } + attr=attr_from_stat(&statbuf); + sftp_reply_names_add(msg,dir->d_name,file,attr); + sftp_attributes_free(attr); + } + /* if there was at least one file, don't send the eof yet */ + if(i==0 && handle->eof){ + sftp_reply_status(msg,SSH_FX_EOF,NULL); + return 0; + } + sftp_reply_names(msg); + return 0; +} + +int handle_close(SFTP_CLIENT_MESSAGE *msg){ + struct sftp_handle *handle=sftp_handle(msg->sftp,msg->handle); + if(!handle){ + sftp_reply_status(msg,SSH_FX_BAD_MESSAGE,"invalid handle"); + return 0; + } + sftp_handle_remove(msg->sftp,handle); + if(handle->type==TYPE_DIR){ + closedir(handle->dir); + } else { + fclose(handle->file); + } + if(handle->name) + free(handle->name); + free(handle); + sftp_reply_status(msg,SSH_FX_OK,NULL); + return 0; +} + +int sftploop(SSH_SESSION *session, SFTP_SESSION *sftp){ + SFTP_CLIENT_MESSAGE *msg; + char buffer[PATH_MAX]; + do { + msg=sftp_get_client_message(sftp); + if(!msg) + break; + switch(msg->type){ + case SFTP_REALPATH: + ssh_say(1,"client realpath : %s\n",msg->filename); + realpath(msg->filename,buffer); + ssh_say(2,"responding %s\n",buffer); + sftp_reply_name(msg, buffer, NULL); + break; + case SFTP_OPENDIR: + ssh_say(1,"client opendir(%s)\n",msg->filename); + handle_opendir(msg); + break; + case SFTP_LSTAT: + ssh_say(1,"client stat(%s)\n",msg->filename); + handle_lstat(msg); + break; + case SFTP_READDIR: + ssh_say(1,"client readdir\n"); + handle_readdir(msg); + break; + case SFTP_CLOSE: + ssh_say(1,"client close\n"); + handle_close(msg); + break; + } + sftp_client_message_free(msg); + } while (1); + if(!msg) + return 1; + return 0; +} + +int do_auth(SSH_SESSION *session){ + SSH_MESSAGE *message; + int auth=0; + do { + message=ssh_message_get(session); + if(!message) + break; + switch(ssh_message_type(message)){ + case SSH_AUTH_REQUEST: + switch(ssh_message_subtype(message)){ + case SSH_AUTH_PASSWORD: + printf("User %s wants to auth with pass %s\n", + ssh_message_auth_user(message), + ssh_message_auth_password(message)); + if(auth_password(ssh_message_auth_user(message), + ssh_message_auth_password(message))){ + auth=1; + ssh_message_auth_reply_success(message,0); + break; + } + // not authenticated, send default message + case SSH_AUTH_NONE: + ssh_message_auth_reply_success(message,0); + auth=1; + break; + default: + ssh_message_auth_set_methods(message,SSH_AUTH_PASSWORD); + ssh_message_reply_default(message); + break; + } + break; + default: + ssh_message_reply_default(message); + } + ssh_message_free(message); + } while (!auth); + return auth; +} + +CHANNEL *recv_channel(SSH_SESSION *session){ + CHANNEL *chan=NULL; + SSH_MESSAGE *message; + int sftp=0; + do { + message=ssh_message_get(session); + if(message){ + switch(ssh_message_type(message)){ + case SSH_CHANNEL_REQUEST_OPEN: + if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){ + chan=ssh_message_channel_request_open_reply_accept(message); + break; + } + default: + ssh_message_reply_default(message); + } + ssh_message_free(message); + } + } while(message && !chan); + if(!chan) + return NULL; + do { + message=ssh_message_get(session); + if(message && ssh_message_type(message)==SSH_CHANNEL_REQUEST && + ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SUBSYSTEM){ + if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){ + sftp=1; + ssh_message_channel_request_reply_success(message); + break; + } + } + if(!sftp){ + ssh_message_reply_default(message); + } + ssh_message_free(message); + } while (message && !sftp); + if(!message) + return NULL; + return chan; +} + +int main(int argc, char **argv){ + SSH_OPTIONS *options=ssh_options_new(); + SSH_SESSION *session; + SSH_BIND *ssh_bind; + CHANNEL *chan=NULL; + SFTP_SESSION *sftp=NULL; + ssh_options_getopt(options,&argc,argv); + ssh_options_set_dsa_server_key(options,"/etc/ssh/ssh_host_dsa_key"); + ssh_options_set_rsa_server_key(options,"/etc/ssh/ssh_host_rsa_key"); + ssh_bind=ssh_bind_new(); + ssh_bind_set_options(ssh_bind,options); + if(ssh_bind_listen(ssh_bind)<0){ + printf("Error listening to socket: %s\n",ssh_get_error(ssh_bind)); + return 1; + } + session=ssh_bind_accept(ssh_bind); + if(!session){ + printf("error accepting a connection : %s\n",ssh_get_error(ssh_bind)); + return 1; + } + printf("Socket connected : %d\n",ssh_get_fd(session)); + if(ssh_accept(session)){ + printf("ssh_accept : %s\n",ssh_get_error(session)); + return 1; + } + if(do_auth(session)<=0){ + printf("error : %s\n",ssh_get_error(session)); + return 1; + } + printf("user authenticated\n"); + chan=recv_channel(session); + if(!chan){ + printf("error : %s\n",ssh_get_error(session)); + return 1; + } + sftp=sftp_server_new(session,chan); + if(sftp_server_init(sftp)){ + printf("error : %s\n",ssh_get_error(session)); + return 1; + } + printf("Sftp session open by client\n"); + sftploop(session,sftp); + ssh_disconnect(session); + return 0; +} + |