From 812c36fe9d6820e9b41826c84e9bc81ffde04193 Mon Sep 17 00:00:00 2001 From: rd235 Date: Mon, 28 Apr 2008 15:44:07 +0000 Subject: [PATCH] SHA1 passwd mgmt (by Marco Dalla Via) git-svn-id: https://vde.svn.sourceforge.net/svnroot/vde/trunk@256 d37a7db1-d92d-0410-89df-f68f52f87b57 --- vdetelweb/Makefile.am | 1 + vdetelweb/README | 7 ++- vdetelweb/telnet.c | 27 ++++++------ vdetelweb/vdetelweb.c | 78 +++++++++++++++++++++++--------- vdetelweb/vdetelweb.h | 11 ++++- vdetelweb/vdetelwebrc | 5 ++- vdetelweb/web.c | 120 ++++++++++++++++++++++++++++++++++++-------------- 7 files changed, 179 insertions(+), 70 deletions(-) diff --git a/vdetelweb/Makefile.am b/vdetelweb/Makefile.am index 6949dd4..b78146e 100644 --- a/vdetelweb/Makefile.am +++ b/vdetelweb/Makefile.am @@ -8,3 +8,4 @@ EXTRA_DIST = ${man_MANS} vdetelwebrc vdetelweb_SOURCES = vdetelweb.c web.c telnet.c vdetelweb.h vdetelweb_LDFLAGS = -ldl -lpthread +vdetelweb_CFLAGS = -Wall diff --git a/vdetelweb/README b/vdetelweb/README index fa6bd26..e92c5ad 100644 --- a/vdetelweb/README +++ b/vdetelweb/README @@ -20,9 +20,13 @@ Different path for the rc file can be given by the -f option. #vdetelweb rc sample ip4=192.168.0.253/24 defroute4=192.168.0.1 -password=piripicchio +password=e8b32ad31b34a21d9fa638c2ee6cf52d46d5106b *********************** END Sample vdetelwebrc file ************************** +The password in the example is "piripicchio". +The hash of the password has been obtained by the following command: +$ echo -n piripicchio | sha1sum + VDETELWEB creates a telnet and/or web interface to a running VDE switch. The switch must have been started with the remote mgmt option (-m). % vde_switch -M /tmp/vde.mgmt -daemon @@ -34,3 +38,4 @@ Launch the tool: Now it is possible to use telnet or a browser to manage the switch. (c) 2005 Renzo Davoli - Department of Computer Science. University of Bologna. +(c) 2008 Renzo Davoli, Marco Dalla Via. Editing of commands and sha1 passwd diff --git a/vdetelweb/telnet.c b/vdetelweb/telnet.c index b40324b..14e4ad8 100644 --- a/vdetelweb/telnet.c +++ b/vdetelweb/telnet.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -99,13 +101,12 @@ static int commonprefix(char *x, char *y,int maxlen) static void showexpand(char *linebuf,int bufindex, int fd) { char *buf; - int bufsize; + size_t bufsize; FILE *ms=open_memstream(&buf,&bufsize); int nmatches=0; if (ms) { if (commandlist && bufindex>0) { char **s=commandlist; - char *match; while (*s) { if (strncmp(linebuf,*s,bufindex)==0) { nmatches++; @@ -126,8 +127,9 @@ static int tabexpand(char *linebuf,int bufindex,int maxlength) { if (commandlist && bufindex>0) { char **s=commandlist; - int nmatches=0,len; - char *match; + int nmatches=0; + int len=0; + char *match=NULL; while (*s) { if (strncmp(linebuf,*s,bufindex)==0) { nmatches++; @@ -166,7 +168,6 @@ static int qstrcmp(const void *a,const void *b) static void create_commandlist() { int vdefd=openextravdem(); - char buf[BUFSIZE]; char linebuf[BUFSIZE]; char *localclist[MAX_KEYWORDS]; int nkeywords=0; @@ -190,7 +191,7 @@ static void create_commandlist() //fprintf(stderr,"%s\n",linebuf); localclist[nkeywords]=strdup(linebuf); if (nkeywordsbufindex+(prompt_too != 0)*strlen(prompt); char *buf; - int bufsize; + size_t bufsize; FILE *ms=open_memstream(&buf,&bufsize); if (ms) { for (j=0;jlinebuf)-st->bufindex; char *buf; - int bufsize; + size_t bufsize; FILE *ms=open_memstream(&buf,&bufsize); if (ms) { if (prompt_too) @@ -312,7 +313,7 @@ void telnet_getanswer(struct telnetstat *st) } } -int vdedata(int fn,int fd,int vdefd) +void vdedata(int fn,int fd,int vdefd) { struct telnetstat *st=status[fn]; erase_line(st,1); @@ -341,7 +342,8 @@ void telnet_core(int fn,int fd,int vdefd) case TELNET_PASSWD+2: while (st->linebuf[st->bufindex-1] == '\n') st->linebuf[--st->bufindex]=0; - if (strcmp(st->linebuf,passwd) != 0) { + + if (!sha1passwdok(st->linebuf)) { st->status++; if (st->status < TELNET_PASSWD + 3) lwip_write(fd,"\r\nlogin incorrect\r\n\r\nPassword: ",30); @@ -471,7 +473,7 @@ static void shift_history(struct telnetstat *st) st->history[0]=NULL; } -int telnetdata(int fn,int fd,int vdefd) +void telnetdata(int fn,int fd,int vdefd) { unsigned char buf[BUFSIZE]; int n,i; @@ -607,7 +609,7 @@ int telnetdata(int fn,int fd,int vdefd) } } -int telnetaccept(int fn,int fd,int vdefd) +void telnetaccept(int fn,int fd,int vdefd) { struct sockaddr_in cli_addr; int newsockfd; @@ -637,7 +639,6 @@ int telnetaccept(int fn,int fd,int vdefd) st->history[i]=0; lwip_write(newsockfd,banner,strlen(banner)); lwip_write(newsockfd,"\r\nLogin: ",9); - return 0; } void telnet_init(int vdefd) diff --git a/vdetelweb/vdetelweb.c b/vdetelweb/vdetelweb.c index 1e9f9e9..4f232a7 100644 --- a/vdetelweb/vdetelweb.c +++ b/vdetelweb/vdetelweb.c @@ -3,9 +3,12 @@ * * vdetelweb.c: main * - * Copyright 2005 Renzo Davoli University of Bologna - Italy + * Copyright 2005,2008 Virtual Square Team University of Bologna - Italy + * 2005 written by Renzo Davoli * --pidfile/-p and cleanup management by Mattia Belletti (C) 2004 * (copied from vde_switch code). + * 2008 updated Renzo Davoli + * 2008 sha1sum by Marco Dalla Via * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,23 +28,25 @@ * */ #include -#include -#include +#include +#include #include #include -#include +#include +#include #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -56,15 +61,15 @@ char *banner; char *progname; char *prompt; int logok; -char *passwd; +static char *passwd; static char *pidfile = NULL; static char pidfile_path[_POSIX_PATH_MAX]; #define MAXFD 16 +#define HASH_SIZE 40 int npfd=0; struct pollfd pfd[MAXFD]; -typedef int (*intfun)(); -intfun fpfd[MAXFD]; +voidfun fpfd[MAXFD]; void *status[MAXFD]; #define ROOTCONFFILE "/etc/vde/vdetelwebrc" @@ -93,6 +98,38 @@ static void cleanup(void) } } +int sha1passwdok(const char *pw) { + char buf[HASH_SIZE + 1]; + int pfd_fc[2]; + int pfd_cf[2]; + pid_t pid; + + pipe(pfd_fc); + pipe(pfd_cf); + pid = fork(); + + if (!pid) { + close(pfd_fc[1]); + close(pfd_cf[0]); + dup2(pfd_fc[0], STDIN_FILENO); + dup2(pfd_cf[1], STDOUT_FILENO); + + execl("/usr/bin/sha1sum", "/usr/bin/sha1sum", NULL); + exit(1); + } else { + close(pfd_cf[1]); + close(pfd_fc[0]); + + write(pfd_fc[1], pw, strlen(pw)); + close(pfd_fc[1]); + read(pfd_cf[0], buf, sizeof(buf)); + close(pfd_cf[0]); + + waitpid(pid, NULL, 0); + return (strncmp(buf,passwd,strlen(passwd))==0); + } +} + static void sig_handler(int sig) { cleanup(); @@ -257,7 +294,7 @@ static void readip(char *arg,struct netif *nif,int af) int err; memset(&hint,0,sizeof(hint)); hint.ai_family=af; - if (err=getaddrinfo(arg,NULL,&hint,&res)) + if ((err=getaddrinfo(arg,NULL,&hint,&res))!=0) printlog(LOG_ERR,"ip address %s error %s",arg,gai_strerror(err)); else { switch(res->ai_family) { @@ -275,7 +312,6 @@ static void readip(char *arg,struct netif *nif,int af) break; case PF_INET6:{ struct sockaddr_in6 *in=(struct sockaddr_in6 *)res->ai_addr; - char i; unsigned char *addr=in->sin6_addr.s6_addr; sockaddr2ip_6addr(&ipaddr,addr); bitno2mask(addr,bitno,16); @@ -294,11 +330,11 @@ static void readip(char *arg,struct netif *nif,int af) static void readdefroute(char *arg,struct netif *nif,int af) { struct addrinfo *res,hint; - struct ip_addr ipaddr,netmask; + struct ip_addr ipaddr; int err; memset(&hint,0,sizeof(hint)); hint.ai_family=af; - if (err=getaddrinfo(arg,NULL,&hint,&res)) + if ((err=getaddrinfo(arg,NULL,&hint,&res))!=0) printlog(LOG_ERR,"ip address %s error %s",arg,gai_strerror(err)); else { switch(res->ai_family) { @@ -314,7 +350,6 @@ static void readdefroute(char *arg,struct netif *nif,int af) break; case PF_INET6:{ struct sockaddr_in6 *in=(struct sockaddr_in6 *)res->ai_addr; - char i; sockaddr2ip_6addr(&ipaddr,in->sin6_addr.s6_addr); lwip_add_route(IP_ADDR_ANY,IP_ADDR_ANY,&ipaddr,nif,0); } @@ -381,7 +416,7 @@ int readconffile(char *path,struct netif *nif) return 0; } -int addpfd(int fd,intfun cb) +int addpfd(int fd,voidfun cb) { if (npfd < MAXFD) { pfd[npfd].fd=fd; @@ -551,7 +586,6 @@ int main(int argc, char *argv[]) printlog(LOG_ERR,"configuration file not found"); exit(1); } - //sleep(10); if (telnet) telnet_init(vdefd); if (web) diff --git a/vdetelweb/vdetelweb.h b/vdetelweb/vdetelweb.h index 5c552e9..7660eef 100644 --- a/vdetelweb/vdetelweb.h +++ b/vdetelweb/vdetelweb.h @@ -2,12 +2,21 @@ #define _VDETELWEB_H #define BUFSIZE 1024 #define LWIPV6DL +typedef void (*voidfun)(); + extern void *status[]; extern char *banner; -extern char *passwd; extern char *prompt; +int sha1passwdok(const char *pw); +int addpfd(int fd,voidfun cb); +void delpfd(int fn); +int pfdsearch(int fd); +int openextravdem(); +void telnet_init(int vdefd); +void web_init(int vdefd); + void printlog(int priority, const char *format, ...); #endif diff --git a/vdetelweb/vdetelwebrc b/vdetelweb/vdetelwebrc index 561c50f..4cd84fe 100644 --- a/vdetelweb/vdetelwebrc +++ b/vdetelweb/vdetelwebrc @@ -5,4 +5,7 @@ defroute=192.168.250.1 #defroute4=192.168.250.1 ip=2001:760:2e00:ff00::5556/64 defroute=2001:760:2e00:ff00::1 -password=piripicchio +# to create a new passwd run the following command: +# $ echo -n piripicchio | sha1sum +# typing your passwd instead of "piripicchio" +password=e8b32ad31b34a21d9fa638c2ee6cf52d46d5106b diff --git a/vdetelweb/web.c b/vdetelweb/web.c index 43dca80..1ce8925 100644 --- a/vdetelweb/web.c +++ b/vdetelweb/web.c @@ -3,7 +3,10 @@ * * web.c: http micro server for vde mgmt * - * Copyright 2005 Renzo Davoli University of Bologna - Italy + * Copyright 2005 Virtual Square Team University of Bologna - Italy + * written by Renzo Davoli 2005 + * management of sha1 Marco Dalla Via 2008 + * modified by Renzo Davoli 2008 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +32,8 @@ #include #include #include +#include +#include #include #include #include @@ -50,9 +55,9 @@ #define WEB_OP_POST 0x1 #define WEB_OP_POSTDATA 0x2 -static char base64ab[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static char *base64passwd; -typedef void (*voidfun)(); +const char b64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +//static char *base64passwd; struct webstat { unsigned char status; unsigned char op; @@ -62,45 +67,83 @@ struct webstat { int bufindex; }; - static void lowercase(char *s) { while (*s != 0) { - tolower(*s); + *s = tolower(*s); s++; } } -static convert2base64(char *from,char *to,int tosize) -{ +void encode64(const char *from, char *to, int tosize) { + int convbuf; - int n=strlen(from); - while (n>0 && tosize>3) { - convbuf=*from; - from++;n--; - convbuf<<=8; - if (n>0) convbuf|=*from; - from++;n--; - convbuf<<=8; - if (n>0) convbuf|=*from; - from++;n--; - *(to++)=base64ab[convbuf>>18]; - *(to++)=base64ab[convbuf>>12 & 0x3f]; - *(to++)=(n<-1)?'=':base64ab[convbuf>>6 & 0x3f]; - *(to++)=(n<0)?'=':base64ab[convbuf & 0x3f]; + int n = strlen(from); + + while ((n > 0) && (tosize > 3)) { + + convbuf = *from; + from++; + n--; + convbuf <<= 8; + if (n > 0) + convbuf |= *from; + from++; + n--; + convbuf <<= 8; + if (n > 0) + convbuf |= *from; + from++; + n--; + *(to++) = b64_chars[convbuf >> 18]; + *(to++) = b64_chars[(convbuf >> 12) & 0x3f]; + *(to++) = (n < -1) ? '=' : b64_chars[(convbuf >> 6) & 0x3f]; + *(to++) = (n < 0) ? '=' : b64_chars[convbuf & 0x3f]; tosize -= 4; } - *to=0; + *to = 0; } +void decode64(const char *src, char *dest, int dest_size) { + + int convbuf; + int l = strlen(src); + char c_src[l]; + char *c; + + int i, j; + + strcpy(c_src, src); + + /* Sostitute '=' (paddings) with 0 ['A'] */ + while ((c = strchr(c_src, '=')) != NULL) + *c = 'A'; + + /* Convert 4 byte in 6 bit (64) to 3 byte in 8 bit */ + for (i = 0, j = 0; i < l; i += 4, j += 3) { + + convbuf = (((int)(strchr(b64_chars, c_src[i]) - b64_chars) << 18) + + ((int)(strchr(b64_chars, c_src[i + 1]) - b64_chars) << 12) + + ((int)(strchr(b64_chars, c_src[i + 2]) - b64_chars) << 6) + + ((int)(strchr(b64_chars, c_src[i + 3]) - b64_chars))); + dest[j] = ((convbuf >> 16) & 255); + dest[j + 1] = ((convbuf >> 8) & 255); + dest[j + 2] = ((convbuf & 255)); + } + + dest[j] = '\0'; +} + +#if 0 static void createbase64passwd() { char buf[BUFSIZE]; char buf64[BUFSIZE*4/3]; snprintf(buf,BUFSIZE,"admin:%s",passwd); - convert2base64(buf,buf64,BUFSIZE*4/3); + encode64(buf,buf64,BUFSIZE*4/3); base64passwd=strdup(buf64); } +#endif static void lwip_printf(int fd, const char *format, ...) { @@ -237,7 +280,6 @@ static void vde_helpline(struct vdemenu **headp,char *buf,int len,int indata,int helppos=i; } else if (nl > 2 && indata && (strncmp(buf,"debug",5) !=0 )) { - int i; char *name; char *syntax; char *help; @@ -327,7 +369,7 @@ static void postdata_parse(int fd,int vdefd,char *menu,char *postdata) int l=strlen(token); char *targ=index(token,'='); if(strncmp("X=",token,2) != 0) { - if (targ+1 < token+l) + if (targ+1 < token+l) { if(cmd==NULL) { char *point; if ((point=strstr(token,".arg")) != NULL) @@ -336,6 +378,7 @@ static void postdata_parse(int fd,int vdefd,char *menu,char *postdata) arg=targ+1; } else cmd=""; + } } } if(cmd!=NULL && *cmd != 0) { @@ -450,7 +493,7 @@ static void web_menu_index(int fd) static void web_create_page(char *path,int fd,int vdefd,char *postdata) { - struct vdemenu *this; + struct vdemenu *this=NULL; char *tail; if ((tail=strstr(path,".html")) != NULL) *tail=0; @@ -537,9 +580,21 @@ int web_core(int fn,int fd,int vdefd) //printf("BODYLEN %d\n",st->bodylen); return 0; } else if (strncmp(st->linebuf,"Authorization: Basic",20) == 0) { + char passwd_buf[BUFSIZE]; + char *passwd_buf_shift; + int len=strlen(st->linebuf); int k=20; while (st->linebuf[k] == ' ') k++; - if (strncmp(st->linebuf+k,base64passwd,strlen(base64passwd))==0) + while (st->linebuf[len-1] == '\n' || + st->linebuf[len-1] == '\r' || + st->linebuf[len-1] == ' ') { + len--; + st->linebuf[len]=0; + } + /* SHA1 */ + decode64((st->linebuf + k), passwd_buf, strlen(st->linebuf + k)); + passwd_buf_shift = (char *)(strchr(passwd_buf, ':') + 1); + if (sha1passwdok(passwd_buf_shift)) st->status=WEB_AUTHORIZED; return 0; } else if (st->linebuf[0]=='\n' || st->linebuf[0]=='\r') { @@ -561,12 +616,14 @@ int web_core(int fn,int fd,int vdefd) st->op=WEB_OP_POSTDATA; return 0; } + default: + return 0; } } else return 0; } -int webdata(int fn,int fd,int vdefd) +void webdata(int fn,int fd,int vdefd) { char buf[BUFSIZE]; int n,i; @@ -592,7 +649,7 @@ int webdata(int fn,int fd,int vdefd) } } -int webaccept(int fn,int fd,int vdefd) +void webaccept(int fn,int fd,int vdefd) { struct sockaddr_in cli_addr; int newsockfd; @@ -612,7 +669,6 @@ int webaccept(int fn,int fd,int vdefd) st->status=WEB_IDENTIFY; st->op=0; st->bufindex=0; - return 0; } void web_init(int vdefd) @@ -646,7 +702,7 @@ void web_init(int vdefd) lwip_listen(sockfd, 5); - createbase64passwd(); + //createbase64passwd(); menuhead=vde_gethelp(vdefd); addpfd(sockfd,webaccept); } -- 2.11.4.GIT