static int cifs_server(CLI *c) { u8 buffer[128]; u8 response_access_denied[5] = {0x83, 0, 0, 1, 0x81}; u8 response_use_ssl[5] = {0x83, 0, 0, 1, 0x8e}; u16 len; if(read_blocking(c, c->local_rfd.fd, buffer, 4)<0) /* NetBIOS header */ return -1; len=buffer[3]; len|=(u16)(buffer[2]) << 8; if(len>sizeof(buffer)-4) { s_log(LOG_ERR, "Received block too long"); return -1; } if(read_blocking(c, c->local_rfd.fd, buffer+4, len)<0) return -1; if(buffer[0]!=0x81){ /* NB_SSN_REQUEST */ s_log(LOG_ERR, "Client did not send session setup"); write_blocking(c, c->local_wfd.fd, response_access_denied, 5); return -1; } if(write_blocking(c, c->local_wfd.fd, response_use_ssl, 5)<0) return -1; return 0; /* OK */ }
static int auth_libwrap(CLI *c) { #ifdef USE_LIBWRAP struct request_info request; int fd[2]; int result=0; /* deny by default */ if(pipe(fd)<0) { ioerror("pipe"); return -1; } if(alloc_fd(fd[0]) || alloc_fd(fd[1])) return -1; switch(fork()) { case -1: /* error */ close(fd[0]); close(fd[1]); ioerror("fork"); return -1; case 0: /* child */ close(fd[0]); /* read side */ request_init(&request, RQ_DAEMON, c->opt->servname, RQ_FILE, c->local_rfd.fd, 0); fromhost(&request); result=hosts_access(&request); write_blocking(c, fd[1], (u8 *)&result, sizeof(result)); /* ignore the returned error */ close(fd[1]); /* write side */ _exit(0); default: /* parent */ close(fd[1]); /* write side */ read_blocking(c, fd[0], (u8 *)&result, sizeof(result)); /* ignore the returned error */ close(fd[0]); /* read side */ /* no need to wait() for zombies here: * - in UCONTEXT/PTHREAD mode they're removed using the signal pipe * - in FORK mode they're removed with the client process */ } if(!result) { s_log(LOG_WARNING, "Connection from %s REFUSED by libwrap", c->accepting_address); s_log(LOG_DEBUG, "See hosts_access(5) manual for details"); return -1; /* FAILED */ } s_log(LOG_DEBUG, "Connection from %s permitted by libwrap", c->accepting_address); #endif return 0; /* OK */ }
static int cifs_client(CLI *c) { u8 buffer[5]; u8 request_dummy[4] = {0x81, 0, 0, 0}; /* a zero-length request */ if(write_blocking(c, c->remote_fd.fd, request_dummy, 4)<0) return -1; if(read_blocking(c, c->remote_fd.fd, buffer, 5)<0) { s_log(LOG_ERR, "Failed to read NetBIOS response"); return -1; } if(buffer[0]!=0x83) { /* NB_SSN_NEGRESP */ s_log(LOG_ERR, "Negative response expected"); return -1; } if(buffer[2]!=0 || buffer[3]!=1) { /* length != 1 */ s_log(LOG_ERR, "Unexpected NetBIOS response size"); return -1; } if(buffer[4]!=0x8e) { /* use SSL */ s_log(LOG_ERR, "Remote server does not require SSL"); return -1; } return 0; /* OK */ }
void libwrap_auth(CLI *c, char *accepted_address) { int result=0; /* deny by default */ #ifdef USE_PTHREAD static volatile int num_busy=0, roundrobin=0; int retval, my_process; static pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond=PTHREAD_COND_INITIALIZER; #endif /* USE_PTHREAD */ if(!c->opt->option.libwrap) /* libwrap is disabled for this service */ return; /* allow connection */ #ifdef HAVE_STRUCT_SOCKADDR_UN if(c->peer_addr.sa.sa_family==AF_UNIX) { s_log(LOG_INFO, "Libwrap is not supported on Unix sockets"); return; } #endif #ifdef USE_PTHREAD if(num_processes) { s_log(LOG_DEBUG, "Waiting for a libwrap process"); retval=pthread_mutex_lock(&mutex); if(retval) { errno=retval; ioerror("pthread_mutex_lock"); longjmp(c->err, 1); } while(num_busy==num_processes) { /* all child processes are busy */ retval=pthread_cond_wait(&cond, &mutex); if(retval) { errno=retval; ioerror("pthread_cond_wait"); longjmp(c->err, 1); } } while(busy[roundrobin]) /* find a free child process */ roundrobin=(roundrobin+1)%num_processes; my_process=roundrobin; /* the process allocated by this thread */ ++num_busy; /* the child process has been allocated */ busy[my_process]=1; /* mark the child process as busy */ retval=pthread_mutex_unlock(&mutex); if(retval) { errno=retval; ioerror("pthread_mutex_unlock"); longjmp(c->err, 1); } s_log(LOG_DEBUG, "Acquired libwrap process #%d", my_process); write_fd(ipc_socket[2*my_process], c->opt->servname, strlen(c->opt->servname)+1, c->local_rfd.fd); read_blocking(c, ipc_socket[2*my_process], (u8 *)&result, sizeof result); s_log(LOG_DEBUG, "Releasing libwrap process #%d", my_process); retval=pthread_mutex_lock(&mutex); if(retval) { errno=retval; ioerror("pthread_mutex_lock"); longjmp(c->err, 1); } busy[my_process]=0; /* mark the child process as free */ --num_busy; /* the child process has been released */ if(num_busy==num_processes-1) { /* need to wake up a thread */ retval=pthread_cond_signal(&cond); /* signal waiting threads */ if(retval) { errno=retval; ioerror("pthread_cond_signal"); longjmp(c->err, 1); } } retval=pthread_mutex_unlock(&mutex); if(retval) { errno=retval; ioerror("pthread_mutex_unlock"); longjmp(c->err, 1); } s_log(LOG_DEBUG, "Released libwrap process #%d", my_process); } else #endif /* USE_PTHREAD */ { /* use original, synchronous libwrap calls */ enter_critical_section(CRIT_LIBWRAP); result=check(c->opt->servname, c->local_rfd.fd); leave_critical_section(CRIT_LIBWRAP); } if(!result) { s_log(LOG_WARNING, "Service [%s] REFUSED by libwrap from %s", c->opt->servname, accepted_address); s_log(LOG_DEBUG, "See hosts_access(5) manual for details"); longjmp(c->err, 1); } s_log(LOG_DEBUG, "Service [%s] permitted by libwrap from %s", c->opt->servname, accepted_address); }