X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=daemon%2Fui.c;h=0f6e701bbe45d5d9d3aab1e46c912d1362754443;hb=b984902c37729827db65bc4271a6cd07ff7c0546;hp=a7717eae3c8054b2ff45e64bedb7257421d44cdf;hpb=0388d7345b17aeb284ad7d6276a2f672ade6ada7;p=doldaconnect.git diff --git a/daemon/ui.c b/daemon/ui.c index a7717ea..0f6e701 100644 --- a/daemon/ui.c +++ b/daemon/ui.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef HAVE_CONFIG_H #include @@ -118,6 +119,7 @@ struct uidata struct uidata *next, *prev; struct socket *sk; struct qcommand *queue, *queuelast; + size_t queuesize; struct authhandle *auth; int close; union @@ -169,8 +171,8 @@ static void notifappend(struct notif *notif, ...); struct uiuser *users = NULL; struct uidata *actives = NULL; -struct socket *tcpsocket = NULL; -struct socket *unixsocket = NULL; +struct lport *tcpsocket = NULL; +struct lport *unixsocket = NULL; static time_t starttime; static wchar_t *quoteword(wchar_t *word) @@ -338,38 +340,40 @@ static void cmd_connect(struct socket *sk, struct uidata *data, int argc, wchar_ { int valid; struct in6_addr mv4lo; + struct sockaddr *remote; if(confgetint("ui", "onlylocal")) { - switch(sk->remote->sa_family) - { - case AF_INET: - valid = ((struct sockaddr_in *)sk->remote)->sin_addr.s_addr == INADDR_LOOPBACK; - break; - case AF_INET6: - inet_pton(AF_INET6, "::ffff:127.0.0.1", &mv4lo); - valid = 0; - if(!memcmp(&((struct sockaddr_in6 *)sk->remote)->sin6_addr, &in6addr_loopback, sizeof(in6addr_loopback))) - valid = 1; - if(!memcmp(&((struct sockaddr_in6 *)sk->remote)->sin6_addr, &mv4lo, sizeof(in6addr_loopback))) + valid = 0; + if(!sockpeeraddr(sk, &remote, NULL)) { + switch(remote->sa_family) + { + case AF_INET: + valid = ((struct sockaddr_in *)remote)->sin_addr.s_addr == INADDR_LOOPBACK; + break; + case AF_INET6: + inet_pton(AF_INET6, "::ffff:127.0.0.1", &mv4lo); + valid = 0; + if(!memcmp(&((struct sockaddr_in6 *)remote)->sin6_addr, &in6addr_loopback, sizeof(in6addr_loopback))) + valid = 1; + if(!memcmp(&((struct sockaddr_in6 *)remote)->sin6_addr, &mv4lo, sizeof(in6addr_loopback))) + valid = 1; + break; + case AF_UNIX: valid = 1; - break; - case AF_UNIX: - valid = 1; - break; - default: - valid = 0; - break; + break; + } + free(remote); } if(!valid) { sq(sk, 0, L"502", L"Only localhost connections allowed to this host", NULL); - sk->close = 1; + closesock(sk); data->close = 1; return; } } - sq(sk, 0, L"201", L"1", L"2", L"Dolda Connect daemon v" VERSION, NULL); + sq(sk, 0, L"201", L"1", L"3", L"Dolda Connect daemon v" VERSION, NULL); } static void cmd_notfound(struct socket *sk, struct uidata *data, int argc, wchar_t **argv) @@ -461,20 +465,20 @@ static void cmd_login(struct socket *sk, struct uidata *data, int argc, wchar_t if(data->uid == -1) { sq(sk, 0, L"506", L"Authentication error", NULL); - flog(LOG_INFO, "user %ls authenticated successfully from %s, but no account existed", data->username, formataddress(sk->remote, sk->remotelen)); + flog(LOG_INFO, "user %ls authenticated successfully from %s, but no account existed", data->username, formatsockpeer(sk)); logout(data); } else if((data->userinfo == NULL) || (data->userinfo->perms & PERM_DISALLOW)) { sq(sk, 0, L"506", L"Authentication error", NULL); - flog(LOG_INFO, "user %ls authenticated successfully from %s, but was not authorized", data->username, formataddress(sk->remote, sk->remotelen)); + flog(LOG_INFO, "user %ls authenticated successfully from %s, but was not authorized", data->username, formatsockpeer(sk)); logout(data); } else { sq(sk, 0, L"200", L"Welcome", NULL); - flog(LOG_INFO, "%ls (UID %i) logged in from %s", data->username, data->uid, formataddress(sk->remote, sk->remotelen)); + flog(LOG_INFO, "%ls (UID %i) logged in from %s", data->username, data->uid, formatsockpeer(sk)); } break; case AUTH_DENIED: sq(sk, 0, L"506", L"Authentication error", L"%ls", (data->auth->text == NULL)?L"":(data->auth->text), NULL); - flog(LOG_INFO, "authentication failed for %ls from %s", data->username, formataddress(sk->remote, sk->remotelen)); + flog(LOG_INFO, "authentication failed for %ls from %s", data->username, formatsockpeer(sk)); logout(data); break; case AUTH_PASS: @@ -535,20 +539,20 @@ static void cmd_pass(struct socket *sk, struct uidata *data, int argc, wchar_t * if(data->uid == -1) { sq(sk, 0, L"506", L"Authentication error", NULL); - flog(LOG_INFO, "user %ls authenticated successfully from %s, but no account existed", data->username, formataddress(sk->remote, sk->remotelen)); + flog(LOG_INFO, "user %ls authenticated successfully from %s, but no account existed", data->username, formatsockpeer(sk)); logout(data); } else if((data->userinfo == NULL) || (data->userinfo->perms & PERM_DISALLOW)) { sq(sk, 0, L"506", L"Authentication error", NULL); - flog(LOG_INFO, "user %ls authenticated successfully from %s, but was not authorized", data->username, formataddress(sk->remote, sk->remotelen)); + flog(LOG_INFO, "user %ls authenticated successfully from %s, but was not authorized", data->username, formatsockpeer(sk)); logout(data); } else { sq(sk, 0, L"200", L"Welcome", NULL); - flog(LOG_INFO, "%ls (UID %i) logged in from %s", data->username, data->uid, formataddress(sk->remote, sk->remotelen)); + flog(LOG_INFO, "%ls (UID %i) logged in from %s", data->username, data->uid, formatsockpeer(sk)); } break; case AUTH_DENIED: sq(sk, 0, L"506", L"Authentication error", L"%ls", (data->auth->text == NULL)?L"":(data->auth->text), NULL); - flog(LOG_INFO, "authentication failed for %ls from %s", data->username, formataddress(sk->remote, sk->remotelen)); + flog(LOG_INFO, "authentication failed for %ls from %s", data->username, formatsockpeer(sk)); logout(data); break; case AUTH_PASS: @@ -694,7 +698,7 @@ static void cmd_lspeers(struct socket *sk, struct uidata *data, int argc, wchar_ { int i; struct fnetnode *fn; - struct fnetpeer *peer; + struct fnetpeer *peer, *npeer; haveargs(2); if((fn = findfnetnode(wcstol(argv[1], NULL, 0))) == NULL) @@ -704,11 +708,12 @@ static void cmd_lspeers(struct socket *sk, struct uidata *data, int argc, wchar_ } if(fn->peers == NULL) { - sq(sk, 0, L"201", L"No peers avaiable", NULL); + sq(sk, 0, L"201", L"No peers available", NULL); } else { - for(peer = fn->peers; peer != NULL; peer = peer->next) + for(peer = btreeiter(fn->peers); peer != NULL; peer = npeer) { - sq(sk, 2 | ((peer->next != NULL)?1:0), L"200", L"%ls", peer->id, L"%ls", peer->nick, NULL); + npeer = btreeiter(NULL); + sq(sk, 2 | ((npeer != NULL)?1:0), L"200", L"%ls", peer->id, L"%ls", peer->nick, NULL); for(i = 0; i < peer->dinum; i++) { if(peer->peerdi[i].datum->datatype == FNPD_INT) @@ -1420,6 +1425,7 @@ static struct qcommand *unlinkqcmd(struct uidata *data) qcmd = data->queue; if(qcmd != NULL) { + data->queuesize--; data->queue = qcmd->next; if(qcmd == data->queuelast) data->queuelast = qcmd->next; @@ -1610,6 +1616,7 @@ static void queuecmd(struct uidata *data, struct command *cmd, int argc, wchar_t data->queuelast = new; if(data->queue == NULL) data->queue = new; + data->queuesize++; } static struct uidata *newuidata(struct socket *sk) @@ -1802,6 +1809,11 @@ static void uiread(struct socket *sk, struct uidata *data) break; } } + if(data->cbdata > 16384) + { + /* Kill clients that send us unreasonably long lines */ + data->close = 1; + } } static void uierror(struct socket *sk, int err, struct uidata *data) @@ -1811,7 +1823,7 @@ static void uierror(struct socket *sk, int err, struct uidata *data) freeuidata(data); } -static void uiaccept(struct socket *sk, struct socket *newsk, void *data) +static void uiaccept(struct lport *lp, struct socket *newsk, void *data) { struct uidata *uidata; @@ -2225,7 +2237,7 @@ static struct sockaddr_un *makeunixname(void) static int tcpportupdate(struct configvar *var, void *uudata) { - struct socket *newsock; + struct lport *newsock; newsock = NULL; if((var->val.num != -1) && ((newsock = netcstcplisten(var->val.num, 1, uiaccept, NULL)) == NULL)) @@ -2235,7 +2247,7 @@ static int tcpportupdate(struct configvar *var, void *uudata) } if(tcpsocket != NULL) { - putsock(tcpsocket); + closelport(tcpsocket); tcpsocket = NULL; } tcpsocket = newsock; @@ -2244,7 +2256,7 @@ static int tcpportupdate(struct configvar *var, void *uudata) static int unixsockupdate(struct configvar *var, void *uudata) { - struct socket *newsock; + struct lport *newsock; struct sockaddr_un *un; mode_t ou; @@ -2259,7 +2271,7 @@ static int unixsockupdate(struct configvar *var, void *uudata) umask(ou); if(unixsocket != NULL) { - putsock(unixsocket); + closelport(unixsocket); unixsocket = NULL; } unixsocket = newsock; @@ -2399,6 +2411,15 @@ static int run(void) freequeuecmd(qcmd); return(1); } + if(data->queuesize > 10) + { + /* Clients should not be queue up commands at all, since + * they should not send a new command before receiving a + * reply to the previous command. Therefore, we + * mercilessly massacre clients which are stacking up too + * many commands. */ + data->close = 1; + } } return(0); } @@ -2408,9 +2429,9 @@ static void terminate(void) while(users != NULL) freeuser(users); if(tcpsocket != NULL) - putsock(tcpsocket); + closelport(tcpsocket); if(unixsocket != NULL) - putsock(unixsocket); + closelport(unixsocket); } static struct configvar myvars[] =