static void init_local(CLI * c) { SOCKADDR_UNION addr; socklen_t addr_len; char *accepted_address; addr_len = sizeof(SOCKADDR_UNION); c->local_rfd.is_socket = !getpeername(c->local_rfd.fd, &addr.sa, &addr_len); if (c->local_rfd.is_socket) { memcpy(&c->peer_addr.sa, &addr.sa, addr_len); c->peer_addr_len = addr_len; if (set_socket_options(c->local_rfd.fd, 1)) s_log(LOG_WARNING, "Failed to set local socket options"); } else { if (get_last_socket_error() != S_ENOTSOCK) { sockerror("getpeerbyname (local_rfd)"); longjmp(c->err, 1); } } if (c->local_rfd.fd == c->local_wfd.fd) { c->local_wfd.is_socket = c->local_rfd.is_socket; } else { addr_len = sizeof(SOCKADDR_UNION); c->local_wfd.is_socket = !getpeername(c->local_wfd.fd, &addr.sa, &addr_len); if (c->local_wfd.is_socket) { if (!c->local_rfd.is_socket) { memcpy(&c->peer_addr.sa, &addr.sa, addr_len); c->peer_addr_len = addr_len; } if (set_socket_options(c->local_wfd.fd, 1)) s_log(LOG_WARNING, "Failed to set local socket options"); } else { if (get_last_socket_error() != S_ENOTSOCK) { sockerror("getpeerbyname (local_wfd)"); longjmp(c->err, 1); } } } if (!c->local_rfd.is_socket && !c->local_rfd.is_socket) { s_log(LOG_NOTICE, "Service [%s] accepted connection", c->opt->servname); return; } accepted_address = s_ntop(&c->peer_addr, c->peer_addr_len); auth_user(c, accepted_address); s_log(LOG_NOTICE, "Service [%s] accepted connection from %s", c->opt->servname, accepted_address); str_free(accepted_address); }
void handle_con(int sock) { printf("---------------------\n"); printf("Handling new connection\n"); int n, uid, tuid; size_t len; char msg[512]; char *user, *pass, *message; len = sizeof(msg); memset(msg, 0, len); n = read(sock, msg, len - 1); if (n < 0) error("error: reading from socket"); // printf("Message: %s\n", msg); /* very simple authentication */ msg[10] = msg[19] = '\0'; /* * login with your user id and the password found in your home directory * e.g. "inetsec999:XXXXXXXX:<message>" * "dazur999 :XXXXXXXX:<message>" * */ user = msg; /* * you will find your password in your home directory on bandit * * please check twice before sending us email ;-) * */ pass = msg + 11; message = msg + 20; //printf("User: %s\n", user); //printf("Password: %s\n", pass); //printf("Message: %s\n", message); if ((uid = auth_user(user, pass)) != 0) { /* change to inetsec or dazur user on bandit */ tuid = uid; //if (setresuid(tuid, tuid, tuid) < 0) //error("error: setting permissions"); respond(message); printf("Finished Handling Connection\n"); } else { fprintf(f,"%s %s Access denied\n",user,pass); fflush(f); } }
int main() { map_init(); auth_init(); printf("%d\n",get_uid_by_name("zwz")); printf("%d\n",get_uid_by_name("zwzmzd")); printf("%d\n",get_uid_by_name("nishi")); printf("%d\n",auth_user("zwz","aaa")); printf("%d\n",auth_user("iii","aaa")); printf("%d\n",auth_user("zwz","mzd")); auth_permission("/pro",1); auth_permission("/",1); auth_permission("/a/a/a/a/a",1); printf("%x\n",auth_permission("/pp",1)); return 0; }
void *doftp(void *sd) { int req, msg_ok, ret = 0,dump; long ssock = (long)sd; ret = auth_user(ssock); if (ret == -1) { close(ssock); return; } while(1) { req = 0; if((readn(ssock,(char *)&req,sizeof(req))) < 0) { printf("server: read error %d\n",errno); return; } req = ntohs(req); switch(req) { case STOREFILE: status=sendfile(ssock); break; case REQUESTFILE: status=recvfile(ssock); break; case MKDIR: status=makedir(ssock); break; case LIST: status=listdir(ssock); break; case DELETEFILE: status=deletefile(ssock); break; case END: printf("Client sent request to end connection.\n"); close(ssock); return; default: break; } if(status==-1) break; } return; }
void *doftp(void *sd) { int req, msg_ok; long ssock = (long)sd; auth_user(ssock); while(1) { req = 0; if((readn(ssock,(char *)&req,sizeof(req))) < 0) { printf("server: read error %d\n",errno); exit(0); } req = ntohs(req); switch(req) { case STOREFILE: sendfile(ssock); break; case REQUESTFILE: recvfile(ssock); break; default: printf("server: command not supported\n"); msg_ok = COMMANDNOTSUPPORTED; msg_ok = htons(msg_ok); if((writen(ssock,(char *)&msg_ok,sizeof(msg_ok))) < 0) { printf("server: write error :%d\n",errno); exit(0); } } } }
int main(int argc, char *argv[]) { char *hostname = "localhost"; //host to use if none supplied char *service = "ftp", filename[50] = ""; //defaulto service port char user[50] = "", pass[50] = "", path[50] = ""; int cmd, connectfd; /*User has to give hostname as a cmd line argument */ if(argc==2) hostname = argv[1]; else { fprintf(stderr, "usage: ./4_HW2_Q1_client.exe [hostname]\n"); exit(1); } //strcpy(service, "4000"); connectfd = connectTCP(hostname, service); printf("Authenticating...\n"); printf("Enter user name: "); scanf("%s", user); printf("Enter password: "******"%s", pass); auth_user (connectfd, user, pass); // printf("Enter file name: "); // scanf("%s", filename); while(1) { printf("Commands supported.\n100:RETR\n200:STOR\n300:MKDIR\n400:END\n600:DELETEFILE\nEnter command: "); //bzero(&cmd, sizeof(cmd)); scanf("%d", &cmd); // fgets(,sizeof Buff,stdin); switch(cmd) { case STOREFILE: printf("Enter file name: "); scanf("%s", filename); storefile(connectfd,filename); break; case REQUESTFILE: printf("Enter file name: "); scanf("%s", filename); readfile(connectfd,filename); break; case MKDIR: printf("Enter Dir name: "); scanf("%s", path); makedir(connectfd, path); break; case DELETEFILE: printf("Enter file name: "); scanf("%s", filename); // printf("Enter path name: "); // scanf("%s", path); deletefile(connectfd,filename,path); break; case LIST: //printf("Enter path name: "); //scanf("%s", path); //listdir(connectfd, path); break; case END: cmd = htons(END); if((writen(connectfd,(char *)&cmd,sizeof(cmd))) < 0) { printf("client: write error: %s\n", strerror(errno)); exit(0); } printf("client: shutting down...\n"); exit(0); default: //bzero(&cmd, sizeof(cmd)); printf("Command not implemented!\n"); } printf("\n\n"); } exit(0); }
void do_select(int msock) { int max_fd, msg_ok, ret = 0, req, max_index, i, client_fd, c_len, total_ready; fd_set rset, wholeset; int client[FD_SETSIZE], n, sock_fd; char buffer[MAXLINE]; struct sockaddr_in client_addr; max_fd = msock; max_index = -1; for(i=0; i<FD_SETSIZE; i++) client[i] = -1; FD_ZERO(&wholeset); FD_SET(msock, &wholeset); while (1) { memcpy(&rset, &wholeset, sizeof(rset)); total_ready = select(max_fd + 1, &rset, NULL, NULL, NULL); if (FD_ISSET(msock, &rset)) { printf("Waiting for client connection\n"); //accept an incoming connection c_len = sizeof(struct sockaddr_in); client_fd = accept(msock, (struct sockaddr *)&client_addr, (socklen_t *)&c_len); if(client_fd == -1) { perror("ERROR: accept()\n"); exit(1); } ret = auth_user(client_fd); if (ret == -1) close(client_fd); else { for(i=0; i<FD_SETSIZE; i++) { if (client[i] < 0) { client[i] = client_fd; break; } } if (i==FD_SETSIZE) { perror("Too many clients\n"); exit(1); } FD_SET(client_fd, &wholeset); if (client_fd > max_fd) max_fd = client_fd; if(i > max_index) max_index = i; if (--total_ready <= 0) continue; } } for(i=0; i<=max_index; i++) { if ((sock_fd = client[i]) < 0) continue; if(FD_ISSET(sock_fd, &rset)) { //doftp((void *)(long)sock_fd); n = readn(sock_fd,(char *)&req,sizeof(req)); if(n <= 0) { close(sock_fd); FD_CLR(sock_fd, &wholeset); client[i] = -1; if (n < 0) printf("server: read error %d\n",errno); //status=endexecution(option); } else { req = ntohs(req); switch(req) { case STOREFILE: status=sendfile(sock_fd); break; case REQUESTFILE: status=recvfile(sock_fd); break; case MKDIR: status=makedir(sock_fd); break; case LIST: status=listdir(sock_fd); break; case DELETEFILE: status=deletefile(sock_fd); break; case END: printf("Client sent request to end connection.\n"); close(sock_fd); FD_CLR(sock_fd, &wholeset); client[i] = -1; break; default: break; } } if(--total_ready <= 0) break; } } } }
int main (int argc, char *argv[]) { int err, fake_argc = 1; char * fake_argv[] = {"hello", 0}; QofBook *book; Account *root; char *request_bufp, *reply_bufp; int rc, sz; /* intitialize the engine */ gnc_engine_init (fake_argc, fake_argv); /* contact the database, which is a flat file for this demo */ /* this should really be an SQL server */ book = qof_book_new (); rc = gnc_book_begin (book, "file:/tmp/demo.xac", FALSE); if (!rc) goto bookerrexit; rc = gnc_book_load (book); if (!rc) goto bookerrexit; /* the root pointer points to our local cache of the data */ root = gnc_book_get_root_account (book); /* --------------------------------------------------- */ /* done with initialization, go into event loop */ while (FCGI_Accept() >= 0) { GList *split_list; Query *q = NULL; const char *request_method; const char *user_agent; const char *auth_string; const char *content_length; int read_len = 0; int send_accts = 0; /* get the user agent; reject if wrong agent */ user_agent = getenv ("HTTP_USER_AGENT"); if (strncmp ("gnucash", user_agent, 7)) { reject_user_agent (user_agent); continue; } /* get the request method */ request_method = getenv ("REQUEST_METHOD"); if (strcmp ("POST", request_method)) { /* method=post is the only spported method*/ reject_method(request_method); continue; } /* ----------------------------------------------- */ /* look for an authentication cookie */ auth_string = find_cookie ("gnc-server"); /* found the cookie, lets make sure that it is valid */ if (auth_string) { gboolean valid_session; valid_session = have_session (auth_string); if (!valid_session) { /* XXX invalid sessions are a sign of hacking; * this event should be noted in a security log * and the server admin contacted. */ reject_session (auth_string); continue; } } /* go ahead and read the message body. * we'll need this soon enough */ content_length = getenv("CONTENT_LENGTH"); read_len = atoi (content_length); /* read 'read_len' bytes from stdin ... */ request_bufp = (char *) g_malloc (read_len); fread (request_bufp, read_len, 1, stdin); /* if no previously authenticated session, * authenticate now */ if (!auth_string) { char *name = NULL, *passwd = NULL; parse_for_login (request_bufp, &name, &passwd); auth_string = auth_user (name, passwd); if (!auth_string) { reject_auth(); g_free (request_bufp); continue; } send_accts = 1; } /* ----------------------------------------------- */ /* send only the accounts to the user */ if (send_accts) { /* print the HTTP header */ printf("Content-type: text/gnc-xml\r\n" "Set-Cookie: %s\r\n" "Content-Length: %d\r\n" "\r\n", auth_string, sz); /* since this is the first time the user is logging * in, send them the full set of accounts. * (Do not send them any transactions yet). */ gncxml_write_account_tree_to_buf(root, &reply_bufp, &sz); /* send the xml to the client */ printf ("%s", reply_bufp); g_free (request_bufp); /* wait for the next request */ continue; } /* ----------------------------------------------- */ /* If we got to here, then the ser should be sending * us a query xml. * we should somehow error check that what we got * is really a valid query */ /* conver the xml input into a gnucash query structure... */ q = gncxml_read_query (request_bufp, read_len); xaccQuerySetGroup (q, root); /* hack -- limit to 30 splits ... */ xaccQuerySetMaxSplits (q, 30); split_list = xaccQueryGetSplits (q); /* poke those splits into an ccount group structure */ /* XXX not implemented */ /* send the account group structure back to the user */ /* XXX not implemented */ xaccFreeQuery (q); g_free (request_bufp); } bookerrexit: err = gnc_book_get_error (book); /* 500 Server Error */ FCGI_SetExitStatus (500); printf("Content-type: text/plain\r\n\r\n" "error was %s\n", strerror (err)); FCGI_Finish(); /* close the book */ qof_book_destroy (book); /* shut down the engine */ gnc_engine_shutdown (); sleep (1); /* must return a non-zero error code, otherwise fastcgi * attempts to respawn this daemon. */ return 500; }
static void init_local(CLI *c) { SOCKADDR_UNION addr; socklen_t addr_len; char *accepted_address; /* check if local_rfd is a socket and get peer address */ addr_len=sizeof(SOCKADDR_UNION); c->local_rfd.is_socket=!getpeername(c->local_rfd.fd, &addr.sa, &addr_len); if(c->local_rfd.is_socket) { memcpy(&c->peer_addr.sa, &addr.sa, addr_len); c->peer_addr_len=addr_len; if(set_socket_options(c->local_rfd.fd, 1)) s_log(LOG_WARNING, "Failed to set local socket options"); } else { if(get_last_socket_error()!=S_ENOTSOCK) { sockerror("getpeerbyname (local_rfd)"); longjmp(c->err, 1); } } /* check if local_wfd is a socket and get peer address */ if(c->local_rfd.fd==c->local_wfd.fd) { c->local_wfd.is_socket=c->local_rfd.is_socket; } else { addr_len=sizeof(SOCKADDR_UNION); c->local_wfd.is_socket=!getpeername(c->local_wfd.fd, &addr.sa, &addr_len); if(c->local_wfd.is_socket) { if(!c->local_rfd.is_socket) { /* already retrieved */ memcpy(&c->peer_addr.sa, &addr.sa, addr_len); c->peer_addr_len=addr_len; } if(set_socket_options(c->local_wfd.fd, 1)) s_log(LOG_WARNING, "Failed to set local socket options"); } else { if(get_last_socket_error()!=S_ENOTSOCK) { sockerror("getpeerbyname (local_wfd)"); longjmp(c->err, 1); } } } /* neither of local descriptors is a socket */ if(!c->local_rfd.is_socket && !c->local_rfd.is_socket) { #ifndef USE_WIN32 if(c->opt->option.transparent_src) { s_log(LOG_ERR, "Transparent source needs a socket"); longjmp(c->err, 1); } #endif s_log(LOG_NOTICE, "Service [%s] accepted connection", c->opt->servname); return; } /* authenticate based on retrieved IP address of the client */ accepted_address=s_ntop(&c->peer_addr, c->peer_addr_len); #ifdef USE_LIBWRAP libwrap_auth(c, accepted_address); #endif /* USE_LIBWRAP */ auth_user(c, accepted_address); s_log(LOG_NOTICE, "Service [%s] accepted connection from %s", c->opt->servname, accepted_address); str_free(accepted_address); }
void User::set_email(const std::string& email) { Server::instance()->auth_service().verifyEmailAddress(auth_user(), email); }
void process_data(const std::string &data, const std::string &dbpath, WOLFSSL *sslconn) { //format is cmd:user:secretkey:<possible b64 string> std::vector<std::string> cmdparts; std::stringstream ss(data); std::string part; std::string cmd; std::string user; std::string secret; std::string b64dat; char reply; while(std::getline(ss,part,':')) { if (part != "" && part != " ") cmdparts.push_back(part); } if (cmdparts.size() < 3) { std::cout<<"[-] Client sent an invalid command"<<std::endl; return; } if (cmdparts.size() >= 3) { cmd = cmdparts[0]; user = cmdparts[1]; secret = cmdparts[2]; } if (cmdparts.size() == 4) { b64dat = cmdparts[3]; } //std::cout<<"[DEBUG] "<<data<<std::endl; /* client wishes to register */ if (cmd == "REGISTER") { if (cmdparts.size() == 3) { if (!register_user(user,secret,dbpath)) { std::cout<<"[-] "<<"Failed to register user: "******"[+] "<<"Successfully registered user: "******"[-] Client sent an invalid command"<<std::endl; } if (wolfSSL_write(sslconn, &reply, sizeof(char)) != sizeof(char)) std::cout<< "[-] " << "Failed to notify client of registration status" << std::endl; return; } bool authsuccess = auth_user(user,secret,dbpath); Json::Value root; Json::Value val; Json::StreamWriterBuilder builder; std::string tmp = ""; int loginattempts = 0; if (!read_user_db(&root,dbpath)) return; /* authenticate user before any command processing */ if (!authsuccess) { std::cout<<"[-] "<<user<<" failed to authenticate"<<std::endl; if (root["users"].isMember(user)) { if (root["users"][user].isMember("loginattempts")) { val = root["users"][user]["loginattempts"]; tmp = Json::writeString(builder,val); loginattempts = atoi(tmp.c_str()); //DEBUG //std::cout << tmp << std::endl; //std::cout << loginattempts << std::endl; } loginattempts += 1; root["users"][user]["loginattempts"] = loginattempts; if (!write_user_db(&root, dbpath)) return; } return; } else { if (root["users"].isMember(user)) root["users"][user]["loginattempts"] = 0; if (write_user_db(&root, dbpath)) std::cout<<"[+] "<<user<<" authenticated successfully"<<std::endl; else std::cout << "[-] Failed to write to user database!" << std::endl; } /* client wishes to upload their database */ if (cmd == "UPLOAD") { if (cmdparts.size() == 4) { if (!update_file(user,b64dat)) { std::cout<<"[-] Failed to update "<<user<<"'s"<<" database"<<std::endl; reply = 0; } else { std::cout<<"[+] Updated "<<user<<"'s"<<" database"<<std::endl; reply = 1; } } else { std::cout<<"[-] Client sent an invalid command"<<std::endl; } if (wolfSSL_write(sslconn, &reply, sizeof(char)) != sizeof(char)) std::cout<< "[-] " << "Failed to notify client of chpass status" << std::endl; } /* client wishes to download their database */ else if (cmd == "DOWNLOAD") { if (cmdparts.size() == 3) { if (!send_file(user,sslconn)) std::cout<<"[-] Failed to send "<<user<<"'s"<<" database"<<std::endl; else std::cout<<"[+] Sent "<<user<<"'s"<<" database"<<std::endl; } else { std::cout<<"[-] Client sent an invalid command"<<std::endl; } } else if (cmd == "CHPASS") { //CHPASS:user:curpass:newpass\n if (cmdparts.size() == 4) { //it isn't actually b64-encoded, it's hex.. std::string newpass = b64dat; if (!change_user_pass(user,newpass,dbpath)) { reply = 0; std::cout<<"[-] Failed to change "<<user<<"'s"<<" password"<<std::endl; } else { reply = 1; std::cout<<"[+] Successfully changed "<<user<<"'s"<<" password"<<std::endl; } } else { std::cout<<"[-] Client sent an invalid command"<<std::endl; } if (wolfSSL_write(sslconn, &reply, sizeof(char)) != sizeof(char)) std::cout<< "[-] " << "Failed to notify client of chpass status" << std::endl; } else if (cmd == "TIMESTAMP") { //TIMESTAMP:USER:PASS:time_t value if (cmdparts.size() == 4) { struct stat filestats; std::string userdbpath = user + "_keylocker.db"; //time_t gotmodtime; time_t modtime; std::cout << "[*] Got timestamp request from " << user << std::endl; //file not found, send timestamp of 0 if (stat(userdbpath.c_str(), &filestats) == -1) { std::cout << "[*] " << user << " does not have a database on this server" << std::endl; modtime = 0; } else modtime = filestats.st_mtime; if (wolfSSL_write(sslconn, &modtime, sizeof(time_t)) != sizeof(time_t)) { std::cout << "[-] Failed to notify " << user << " of timestamp" << std::endl; } } else std::cout<<"[-] Client sent an invalid command"<<std::endl; } /* client sent invalid command */ else { std::cout<<"[-] Client sent an invalid command"<<std::endl; } return; }
void nntp(void) { char buf[4096]; int len; while (TRUE) { IsDoing("Waiting"); len = get_nntp(buf, sizeof(buf) -1); if (len < 0) return; if (len == 0) continue; if (strcasestr(buf, (char *)"AUTHINFO PASS") == NULL) { Syslog('n', "< \"%s\"", printable(buf, 0)); } else { Syslog('n', "< \"AUTHINFO PASS ********\""); } if (! check_free()) { send_nntp("400 server closed"); return; } /* * Process received command */ if (strncasecmp(buf, "QUIT", 4) == 0) { send_nntp("205 Goodbye\r\n"); return; } else if (strncasecmp(buf, "AUTHINFO USER", 13) == 0) { auth_user(buf); } else if (strncasecmp(buf, "AUTHINFO PASS", 13) == 0) { auth_pass(buf); } else if (strncasecmp(buf, "ARTICLE", 7) == 0) { if (check_auth(buf)) command_abhs(buf); } else if (strncasecmp(buf, "BODY", 4) == 0) { if (check_auth(buf)) command_abhs(buf); } else if (strncasecmp(buf, "LIST", 4) == 0) { if (check_auth(buf)) command_list(buf); } else if (strncasecmp(buf, "GROUP", 5) == 0) { if (check_auth(buf)) command_group(buf); } else if (strncasecmp(buf, "HEAD", 4) == 0) { if (check_auth(buf)) command_abhs(buf); } else if (strncasecmp(buf, "POST", 4) == 0) { if (check_auth(buf)) command_post(buf); } else if (strncasecmp(buf, "IHAVE", 5) == 0) { send_nntp("435 Article not wanted - do not send it"); } else if (strncasecmp(buf, "NEWGROUPS", 9) == 0) { send_nntp("235 Warning: NEWGROUPS not implemented, returning empty list"); send_nntp("."); } else if (strncasecmp(buf, "NEWNEWS", 7) == 0) { send_nntp("230 Warning: NEWNEWS not implemented, returning empty list"); send_nntp("."); } else if (strncasecmp(buf, "SLAVE", 5) == 0) { send_nntp("202 Slave status noted"); } else if (strncasecmp(buf, "STAT", 4) == 0) { if (check_auth(buf)) command_abhs(buf); } else if (strncasecmp(buf, "MODE READER", 11) == 0) { if (check_auth(buf)) { if (authorized) send_nntp("200 Server ready, posting allowed"); else send_nntp("201 Server ready, no posting allowed"); } } else if (strncasecmp(buf, "XOVER", 5) == 0) { if (check_auth(buf)) command_xover(buf); } else if (strncasecmp(buf, "HELP", 4) == 0) { send_nntp("100 Help text follows"); send_nntp("Recognized commands:"); send_nntp(""); send_nntp("ARTICLE"); send_nntp("AUTHINFO"); send_nntp("BODY"); send_nntp("GROUP"); send_nntp("HEAD"); send_nntp("IHAVE (not implemented, messages are always rejected)"); send_nntp("LIST"); send_nntp("NEWGROUPS (not implemented, always returns an empty list)"); send_nntp("NEWNEWS (not implemented, always returns an empty list)"); send_nntp("POST"); send_nntp("QUIT"); send_nntp("SLAVE (has no effect)"); send_nntp("STAT"); send_nntp("XOVER"); send_nntp(""); send_nntp("FTNNNTP supports most of RFC-977 and also has support for AUTHINFO and"); send_nntp("limited XOVER support (RFC-2980)"); send_nntp("."); } else { send_nntp("500 Unknown command"); } } }
static int init_local(CLI *c) { int addrlen; addrlen=sizeof(c->addr); if(getpeername(c->local_rfd.fd, (struct sockaddr *)&c->addr, &addrlen)<0) { strcpy(c->accepting_address, "NOT A SOCKET"); c->local_rfd.is_socket=0; c->local_wfd.is_socket=0; /* TODO: It's not always true */ #ifdef USE_WIN32 if(get_last_socket_error()!=ENOTSOCK) { #else if(c->opt->option.transparent || get_last_socket_error()!=ENOTSOCK) { #endif sockerror("getpeerbyname"); return -1; } /* Ignore ENOTSOCK error so 'local' doesn't have to be a socket */ } else { safe_ntoa(c->accepting_address, c->addr.sin_addr); c->local_rfd.is_socket=1; c->local_wfd.is_socket=1; /* TODO: It's not always true */ /* It's a socket: lets setup options */ if(set_socket_options(c->local_rfd.fd, 1)<0) return -1; if(auth_libwrap(c)<0) return -1; if(auth_user(c)<0) { log(LOG_WARNING, "Connection from %s:%d REFUSED by IDENT", c->accepting_address, ntohs(c->addr.sin_port)); return -1; } log(LOG_NOTICE, "%s connected from %s:%d", c->opt->servname, c->accepting_address, ntohs(c->addr.sin_port)); } return 0; /* OK */ } static int init_remote(CLI *c) { int fd; /* create connection to host/service */ if(c->opt->local_ip) c->bind_ip=*c->opt->local_ip; #ifndef USE_WIN32 else if(c->opt->option.transparent) c->bind_ip=c->addr.sin_addr.s_addr; #endif else c->bind_ip=0; /* Setup c->remote_fd, now */ if(c->opt->option.remote) { c->resolved_addresses=NULL; fd=connect_remote(c); if(c->resolved_addresses) /* allocated */ free(c->resolved_addresses); } else /* NOT in remote mode */ fd=connect_local(c); if(fd<0) { log(LOG_ERR, "Failed to initialize remote connection"); return -1; } #ifndef USE_WIN32 if(fd>=max_fds) { log(LOG_ERR, "Remote file descriptor out of range (%d>=%d)", fd, max_fds); closesocket(fd); return -1; } #endif log(LOG_DEBUG, "Remote FD=%d initialized", fd); c->remote_fd.fd=fd; c->remote_fd.is_socket=1; /* Always! */ if(set_socket_options(fd, 2)<0) return -1; return 0; /* OK */ }
static int init_local(CLI *c) { SOCKADDR_UNION addr; socklen_t addrlen; addrlen=sizeof(SOCKADDR_UNION); if(getpeername(c->local_rfd.fd, &addr.sa, &addrlen)<0) { strcpy(c->accepting_address, "NOT A SOCKET"); c->local_rfd.is_socket=0; c->local_wfd.is_socket=0; /* TODO: It's not always true */ #ifdef USE_WIN32 if(get_last_socket_error()!=ENOTSOCK) { #else if(c->opt->option.transparent || get_last_socket_error()!=ENOTSOCK) { #endif sockerror("getpeerbyname"); return -1; } /* Ignore ENOTSOCK error so 'local' doesn't have to be a socket */ } else { /* success */ /* copy addr to c->peer_addr */ memcpy(&c->peer_addr.addr[0], &addr, sizeof(SOCKADDR_UNION)); c->peer_addr.num=1; s_ntop(c->accepting_address, &c->peer_addr.addr[0]); c->local_rfd.is_socket=1; c->local_wfd.is_socket=1; /* TODO: It's not always true */ /* It's a socket: lets setup options */ if(set_socket_options(c->local_rfd.fd, 1)<0) return -1; if(auth_libwrap(c)<0) return -1; if(auth_user(c)<0) { s_log(LOG_WARNING, "Connection from %s REFUSED by IDENT", c->accepting_address); return -1; } s_log(LOG_NOTICE, "%s connected from %s", c->opt->servname, c->accepting_address); } return 0; /* OK */ } static int init_remote(CLI *c) { int fd; /* create connection to host/service */ if(c->opt->source_addr.num) memcpy(&c->bind_addr, &c->opt->source_addr, sizeof(SOCKADDR_LIST)); #ifndef USE_WIN32 else if(c->opt->option.transparent) memcpy(&c->bind_addr, &c->peer_addr, sizeof(SOCKADDR_LIST)); #endif else { c->bind_addr.num=0; /* don't bind connecting socket */ } /* Setup c->remote_fd, now */ if(c->opt->option.remote) { fd=connect_remote(c); } else /* NOT in remote mode */ fd=connect_local(c); if(fd<0) { s_log(LOG_ERR, "Failed to initialize remote connection"); return -1; } #ifndef USE_WIN32 if(fd>=max_fds) { s_log(LOG_ERR, "Remote file descriptor out of range (%d>=%d)", fd, max_fds); closesocket(fd); return -1; } #endif s_log(LOG_DEBUG, "Remote FD=%d initialized", fd); c->remote_fd.fd=fd; c->remote_fd.is_socket=1; /* Always! */ if(set_socket_options(fd, 2)<0) return -1; return 0; /* OK */ }
static void init_local(CLI *c) { SOCKADDR_UNION addr; socklen_t addrlen; addrlen=sizeof addr; if(getpeername(c->local_rfd.fd, &addr.sa, &addrlen)<0) { strcpy(c->accepted_address, "NOT A SOCKET"); c->local_rfd.is_socket=0; c->local_wfd.is_socket=0; /* TODO: It's not always true */ #ifdef USE_WIN32 if(get_last_socket_error()!=ENOTSOCK) { #else if(c->opt->option.transparent_src || get_last_socket_error()!=ENOTSOCK) { #endif sockerror("getpeerbyname"); longjmp(c->err, 1); } /* ignore ENOTSOCK error so 'local' doesn't have to be a socket */ } else { /* success */ /* copy addr to c->peer_addr */ memcpy(&c->peer_addr.addr[0], &addr, sizeof addr); c->peer_addr.num=1; s_ntop(c->accepted_address, &c->peer_addr.addr[0]); c->local_rfd.is_socket=1; c->local_wfd.is_socket=1; /* TODO: It's not always true */ /* it's a socket: lets setup options */ if(set_socket_options(c->local_rfd.fd, 1)<0) longjmp(c->err, 1); #ifdef USE_LIBWRAP libwrap_auth(c); #endif /* USE_LIBWRAP */ auth_user(c); s_log(LOG_NOTICE, "Service %s accepted connection from %s", c->opt->servname, c->accepted_address); } } static void init_remote(CLI *c) { /* create connection to host/service */ if(c->opt->source_addr.num) memcpy(&c->bind_addr, &c->opt->source_addr, sizeof(SOCKADDR_LIST)); #ifndef USE_WIN32 else if(c->opt->option.transparent_src) memcpy(&c->bind_addr, &c->peer_addr, sizeof(SOCKADDR_LIST)); #endif else { c->bind_addr.num=0; /* don't bind connecting socket */ } /* setup c->remote_fd, now */ if(c->opt->option.remote) c->remote_fd.fd=connect_remote(c); #ifdef SO_ORIGINAL_DST else if(c->opt->option.transparent_dst) c->remote_fd.fd=connect_transparent(c); #endif /* SO_ORIGINAL_DST */ else /* NOT in remote mode */ c->remote_fd.fd=connect_local(c); c->remote_fd.is_socket=1; /* always! */ s_log(LOG_DEBUG, "Remote FD=%d initialized", c->remote_fd.fd); if(set_socket_options(c->remote_fd.fd, 2)<0) longjmp(c->err, 1); } static void init_ssl(CLI *c) { int i, err; SSL_SESSION *old_session; if(!(c->ssl=SSL_new(c->opt->ctx))) { sslerror("SSL_new"); longjmp(c->err, 1); } SSL_set_ex_data(c->ssl, cli_index, c); /* for callbacks */ SSL_set_session_id_context(c->ssl, (unsigned char *)sid_ctx, strlen(sid_ctx)); if(c->opt->option.client) { #ifndef OPENSSL_NO_TLSEXT if(c->opt->host_name) { s_log(LOG_DEBUG, "SNI: host name: %s", c->opt->host_name); if(!SSL_set_tlsext_host_name(c->ssl, c->opt->host_name)) { sslerror("SSL_set_tlsext_host_name"); longjmp(c->err, 1); } } #endif if(c->opt->session) { enter_critical_section(CRIT_SESSION); SSL_set_session(c->ssl, c->opt->session); leave_critical_section(CRIT_SESSION); } SSL_set_fd(c->ssl, c->remote_fd.fd); SSL_set_connect_state(c->ssl); } else { if(c->local_rfd.fd==c->local_wfd.fd) SSL_set_fd(c->ssl, c->local_rfd.fd); else { /* does it make sence to have SSL on STDIN/STDOUT? */ SSL_set_rfd(c->ssl, c->local_rfd.fd); SSL_set_wfd(c->ssl, c->local_wfd.fd); } SSL_set_accept_state(c->ssl); } /* setup some values for transfer() function */ if(c->opt->option.client) { c->sock_rfd=&(c->local_rfd); c->sock_wfd=&(c->local_wfd); c->ssl_rfd=c->ssl_wfd=&(c->remote_fd); } else { c->sock_rfd=c->sock_wfd=&(c->remote_fd); c->ssl_rfd=&(c->local_rfd); c->ssl_wfd=&(c->local_wfd); } while(1) { #if OPENSSL_VERSION_NUMBER<0x1000002f /* this critical section is a crude workaround for CVE-2010-3864 * * see http://www.securityfocus.com/bid/44884 for details * * NOTE: this critical section also covers callbacks (e.g. OCSP) */ enter_critical_section(CRIT_SSL); #endif /* OpenSSL version < 1.0.0b */ if(c->opt->option.client) i=SSL_connect(c->ssl); else i=SSL_accept(c->ssl); #if OPENSSL_VERSION_NUMBER<0x1000002f leave_critical_section(CRIT_SSL); #endif /* OpenSSL version < 1.0.0b */ err=SSL_get_error(c->ssl, i); if(err==SSL_ERROR_NONE) break; /* ok -> done */ if(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) { s_poll_init(&c->fds); s_poll_add(&c->fds, c->ssl_rfd->fd, err==SSL_ERROR_WANT_READ, err==SSL_ERROR_WANT_WRITE); switch(s_poll_wait(&c->fds, c->opt->timeout_busy, 0)) { case -1: sockerror("init_ssl: s_poll_wait"); longjmp(c->err, 1); case 0: s_log(LOG_INFO, "init_ssl: s_poll_wait:" " TIMEOUTbusy exceeded: sending reset"); longjmp(c->err, 1); case 1: break; /* OK */ default: s_log(LOG_ERR, "init_ssl: s_poll_wait: unknown result"); longjmp(c->err, 1); } continue; /* ok -> retry */ } if(err==SSL_ERROR_SYSCALL) { switch(get_last_socket_error()) { case EINTR: case EAGAIN: continue; } } if(c->opt->option.client) sslerror("SSL_connect"); else sslerror("SSL_accept"); longjmp(c->err, 1); } if(SSL_session_reused(c->ssl)) { s_log(LOG_INFO, "SSL %s: previous session reused", c->opt->option.client ? "connected" : "accepted"); } else { /* a new session was negotiated */ if(c->opt->option.client) { s_log(LOG_INFO, "SSL connected: new session negotiated"); enter_critical_section(CRIT_SESSION); old_session=c->opt->session; c->opt->session=SSL_get1_session(c->ssl); /* store it */ if(old_session) SSL_SESSION_free(old_session); /* release the old one */ leave_critical_section(CRIT_SESSION); } else s_log(LOG_INFO, "SSL accepted: new session negotiated"); print_cipher(c); } }
static void handle_new_connection(int newfd, int epfd) { struct epoll_event ev; struct client_data *client; struct sockaddr_storage addr; socklen_t addrlen = sizeof (addr); char authbuf[AUTHBUFSIZE]; int pos, is_reg, reconnect_id, authlen, userid; static int connection_id = 1; if (fd_to_client_max > newfd && fd_to_client[newfd] == &new_connection_dummy) { epoll_ctl(epfd, EPOLL_CTL_DEL, newfd, &ev); fd_to_client[newfd] = NULL; } /* it should be possible to read immediately due to the "defer" sockopt */ authlen = read(newfd, authbuf, AUTHBUFSIZE - 1); if (authlen <= 0) { close(newfd); return; } getpeername(newfd, (struct sockaddr *)&addr, &addrlen); log_msg("New connection from %s.", addr2str(&addr)); authbuf[authlen] = '\0'; /* make it safe to use as a string */ /* did we receive too much data? */ if (authlen >= AUTH_MAXLEN) { log_msg("Auth buffer overrun attempt from %s? Peer disconnected.", addr2str(&addr)); close(newfd); return; } /* check the end of the received auth data: a JSON object always ends with '}' */ pos = authlen - 1; while (pos > 0 && isspace(authbuf[pos])) pos--; if (authbuf[pos] != '}') { /* not the end of JSON auth data */ log_msg("authentication for %s failed due to incomplete JSON", addr2str(&addr)); return; } /* * ready to authenticate the user here */ userid = auth_user(authbuf, addr2str(&addr), &is_reg, &reconnect_id); if (userid <= 0) { if (!userid) auth_send_result(newfd, AUTH_FAILED_UNKNOWN_USER, is_reg, 0); else auth_send_result(newfd, AUTH_FAILED_BAD_PASSWORD, is_reg, 0); log_msg("authentication failed for %s", addr2str(&addr)); close(newfd); return; } /* user ok, we'll keep this socket */ ev.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET; ev.data.ptr = NULL; ev.data.fd = newfd; if (epoll_ctl(epfd, EPOLL_CTL_ADD, newfd, &ev) == -1) { log_msg("Error in epoll_ctl for %s: %s", addr2str(&addr), strerror(errno)); close(newfd); return; } /* is the client re-establishing a connection to an existing, disconnected game? */ for (client = disconnected_list_head.next; client; client = client->next) if (client->userid == userid && (!reconnect_id || reconnect_id == client->connid)) break; if (reconnect_id && !client) { /* now search through the active connections. The client might have a new IP address, which would leave the socket open and seemingly valid. */ for (client = connected_list_head.next; client; client = client->next) if (client->userid == userid && reconnect_id == client->connid) break; } if (client) { /* there is a running, disconnected game process for this user */ auth_send_result(newfd, AUTH_SUCCESS_RECONNECT, is_reg, client->connid); client->sock = newfd; map_fd_to_client(client->sock, client); client->state = CLIENT_CONNECTED; unlink_client_data(client); link_client_data(client, &connected_list_head); write(client->pipe_out, "\033", 1); /* signal to reset the read buffer */ log_msg("Connection to game at pid %d reestablished for user %d", client->pid, client->userid); return; } else { client = alloc_client_data(&connected_list_head); client->state = CLIENT_CONNECTED; client->sock = newfd; map_fd_to_client(newfd, client); client->connid = connection_id++; client->userid = userid; /* there is no process yet */ if (fork_client(client, epfd)) auth_send_result(newfd, AUTH_SUCCESS_NEW, is_reg, client->connid); /* else: client communication is shutdown if fork_client errors out */ } log_msg("There are now %d clients on the server", client_count); }
/* USER command. Sets global passwd pointer pw if named account exists and is acceptable; sets askpasswd if a PASS command is expected. If logged in previously, need to reset state. */ void user (const char *name) { if (cred.logged_in) { if (cred.guest || cred.dochroot) { reply (530, "Can't change user from guest login."); return; } end_login (&cred); } /* Non zero means failed. */ if (auth_user (name, &cred) != 0) { /* If they gave us a reason. */ if (cred.message) { reply (530, "%s", cred.message); free (cred.message); cred.message = NULL; } else reply (530, "User %s access denied.", name); if (logging) syslog (LOG_NOTICE, "FTP LOGIN REFUSED FROM %s, %s", cred.remotehost, name); return; } /* If the server is set to serve anonymous service only the request have to come from a guest or a chrooted. */ if (anon_only && !cred.guest && !cred.dochroot) { reply (530, "Sorry, only anonymous ftp allowed"); return; } if (logging) { strncpy (curname, name, sizeof (curname) - 1); curname[sizeof (curname) - 1] = '\0'; /* Make sure null terminated. */ } if (cred.message) { reply (331, "%s", cred.message); free (cred.message); cred.message = NULL; } else reply (331, "Password required for %s.", name); askpasswd = 1; /* Delay before reading passwd after first failed attempt to slow down passwd-guessing programs. */ if (login_attempts) sleep ((unsigned) login_attempts); }