コード例 #1
0
void doit(int t) {
  int j;
  SSL *ssl;
  int wstat;
  int sslctl[2];
  char *s;
  unsigned long tmp_long;
  char ssl_cmd;
  stralloc ssl_env = { 0 };
  int bytesleft;
  char envbuf[8192];
  int childpid;
  
  if (pipe(pi) == -1) strerr_die2sys(111,DROP,"unable to create pipe: ");
  if (pipe(po) == -1) strerr_die2sys(111,DROP,"unable to create pipe: ");
  if (socketpair(AF_UNIX, SOCK_STREAM, 0, sslctl) == -1) strerr_die2sys(111,DROP,"unable to create socketpair: ");
 
  if ((j = ip_fmt(&remoteipsa,&remoteaddr)))
    strerr_die3x(111,DROP,"unable to print remote ip",gai_strerror(j));

  if (flagremotehost) {
    if (dns_name(&remotehostsa,&remoteaddr) == 0)
      if (remotehostsa.len) {
	if (flagparanoid) {
	  struct addrinfo *reverse, hints = {0};
	  verifyhost = remoteipsa.s;
	  hints.ai_family = remoteaddr.sa4.sin_family;
	  if (remoteaddr.sa6.sin6_family == AF_INET6) {
	    hints.ai_flags = AI_V4MAPPED | AI_ALL;
	  }
	  if (getaddrinfo(remotehostsa.s, NULL, &hints, &reverse) == 0) {
	    hints.ai_next = reverse;
	    while (hints.ai_next) {
	      if (hints.ai_next->ai_family == AF_INET
		  && remoteaddr.sa4.sin_family == AF_INET
		  && byte_equal(&remoteaddr.sa4.sin_addr, 4, &((struct sockaddr_in*) hints.ai_next->ai_addr)->sin_addr)
		  || hints.ai_next->ai_family == AF_INET6
		     && remoteaddr.sa6.sin6_family == AF_INET6
		     && byte_equal(remoteaddr.sa6.sin6_addr.s6_addr, 16,
				   &((struct sockaddr_in6*) hints.ai_next->ai_addr)->sin6_addr.s6_addr)) {
		flagparanoid = 0;
		break;
	      }
	      hints.ai_next = hints.ai_next->ai_next;
	    }
	    freeaddrinfo(reverse);
	  }
	}
	if (!flagparanoid) {
	  remotehost = remotehostsa.s;
	  verifyhost = remotehostsa.s;
	}
      }
  }

  switch(childpid=fork()) {
    case -1:
      strerr_die2sys(111,DROP,"unable to fork: ");
    case 0:
      /* Child */
      close(sslctl[0]);
      break;
    default:
      /* Parent */
      
      close(pi[0]); close(po[1]); close(sslctl[1]);

      if ((s=env_get("SSL_CHROOT")))
        if (chroot(s) == -1) {
          kill(childpid, SIGTERM);
          strerr_die2x(111,DROP,"unable to chroot");
        }
      
      if ((s=env_get("SSL_GID"))) {
        scan_ulong(s,&tmp_long);
        gid = tmp_long;
      }
      if (gid) if (prot_gid(gid) == -1) {
        kill(childpid, SIGTERM);
        strerr_die2sys(111,FATAL,"unable to set gid: ");
      }

      if ((s=env_get("SSL_UID"))) {
        scan_ulong(s,&tmp_long);
        uid = tmp_long;
      }
      if (uid)
        if (prot_uid(uid) == -1) {
          kill(childpid, SIGTERM);
          strerr_die2sys(111,FATAL,"unable to set uid: ");
        }

      /* Read the TLS command socket.  This will block until/unless
       * TLS is requested.
       */
      if (read(sslctl[0],&ssl_cmd,1) == 1) {
        ssl = ssl_new(ctx,t);
        if (!ssl) {
          kill(childpid, SIGTERM);
          strerr_die2x(111,DROP,"unable to create SSL instance");
        }
        if (ndelay_on(t) == -1) {
          kill(childpid, SIGTERM);
          strerr_die2sys(111,DROP,"unable to set socket options: ");
        }
        if (ssl_timeoutaccept(ssl,ssltimeout) == -1) {
          kill(childpid, SIGTERM);
          strerr_die3x(111,DROP,"unable to accept SSL: ",ssl_error_str(ssl_errno));
        }
      }
        
      if (verbosity >= 2) {
        strnum[fmt_ulong(strnum,getpid())] = 0;
        strerr_warn3("sslserver: ssl ",strnum," accept ",0);
      }
        
      if (flagclientcert) {
        switch(ssl_verify(ssl,verifyhost)) {
          case -1:
	    kill(childpid, SIGTERM);
            strerr_die2x(111,DROP,"unable to verify client certificate");
          case -2:
	    kill(childpid, SIGTERM);
            strerr_die2x(111,DROP,"no client certificate");
          case -3:
	    kill(childpid, SIGTERM);
            strerr_die3x(111,DROP,"certificate name does not match client fqdn: ",verifyhost);
          default: break;
        }
      }
      
      if (ssl_cmd == 'Y') {
        ssl_server_env(ssl, &ssl_env);
        if(!stralloc_0(&ssl_env)) drop_nomem(); /* Add another NUL */
        env("SSLCTL",ssl_env.s); 

        for(bytesleft = ssl_env.len; bytesleft>0; bytesleft-=j)
          if ( (j=write(sslctl[0], ssl_env.s, bytesleft)) < 0) {
            kill(childpid, SIGTERM);
            strerr_die2sys(111, FATAL, "unable to write SSL environment: ");
          }
      }

      if (ssl_cmd == 'Y' || ssl_cmd == 'y') {
        if (ssl_io(ssl,pi[1],po[0],progtimeout) != 0) {
          kill(childpid, SIGTERM);
          strerr_die3x(111,DROP,"unable to speak SSL: ",ssl_error_str(ssl_errno));
        }
        if (wait_nohang(&wstat) > 0)
          _exit(wait_exitcode(wstat)); 
        ssl_close(ssl);
      }
      kill(childpid, SIGTERM);
      _exit(0);
  }

  /* Child-only below this point */

  if (verbosity >= 2) {
    strnum[fmt_ulong(strnum,getpid())] = 0;
    strerr_warn4("sslserver: pid ",strnum," from ",remoteipsa.s,0);
  }

  if (socket_local(t,&localaddr,&localport) == -1)
    strerr_die2sys(111,DROP,"unable to get local address: ");

  if ((j = ip_fmt(&localipsa,&localaddr)))
    strerr_die3x(111,DROP,"unable to print local address: ",gai_strerror(j));
  remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0;

  if (!localhost)
    if (dns_name(&localhostsa,&localaddr) == 0)
      if (localhostsa.len) {
	if (!stralloc_0(&localhostsa)) drop_nomem();
	localhost = localhostsa.s;
      }
  /* If remoteipsa.s contain ':' colon character will assume it is IPv6 */
  if (byte_chr(remoteipsa.s, remoteipsa.len, ':') < remoteipsa.len)
    env("PROTO","SSL6");
  else
    env("PROTO","SSL");
  env("SSLLOCALIP",localipsa.s);
  env("SSLLOCALPORT",localportstr);
  env("SSLLOCALHOST",localhost);
  if (flagtcpenv) {
    env("TCPLOCALIP",localipsa.s);
    env("TCPLOCALPORT",localportstr);
    env("TCPLOCALHOST",localhost);
  }

  env("SSLREMOTEIP",remoteipsa.s);
  env("SSLREMOTEPORT",remoteportstr);
  env("SSLREMOTEHOST",remotehost);
  if (flagtcpenv) {
    env("TCPREMOTEIP",remoteipsa.s);
    env("TCPREMOTEPORT",remoteportstr);
    env("TCPREMOTEHOST",remotehost);
  }

  if (flagremoteinfo) {
    if (remoteinfo(&tcpremoteinfo,&remoteaddr,&localaddr,timeout) == -1)
      flagremoteinfo = 0;
    if (!stralloc_0(&tcpremoteinfo)) drop_nomem();
  }
  env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
  if (flagtcpenv)
    env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);

  if (fnrules) {
    int fdrules;
    fdrules = open_read(fnrules);
    if (fdrules == -1) {
      if (errno != error_noent) drop_rules();
      if (!flagallownorules) drop_rules();
    }
    else {
      if (rules(found,fdrules,&remoteaddr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1)
	drop_rules();
      close(fdrules);
    }
  }

  if (verbosity >= 2) {
    strnum[fmt_ulong(strnum,getpid())] = 0;
    if (!stralloc_copys(&tmp,"sslserver: ")) drop_nomem();
    safecats(flagdeny ? "deny" : "ok");
    cats(" "); safecats(strnum);
    cats(" "); if (localhost) safecats(localhost);
    cats(":"); safecats(localipsa.s);
    cats(":"); safecats(localportstr);
    cats(" "); if (remotehost) safecats(remotehost);
    cats(":"); safecats(remoteipsa.s);
    cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s);
    cats(":"); safecats(remoteportstr);
    cats("\n");
    buffer_putflush(buffer_2,tmp.s,tmp.len);
  }

  if (flagdeny) _exit(100);

  if (gid) if (prot_gid(gid) == -1)
    strerr_die2sys(111,FATAL,"unable to set gid: ");
  if (uid) if (prot_uid(uid) == -1)
    strerr_die2sys(111,FATAL,"unable to set uid: ");

  close(pi[1]); close(po[0]); close(sslctl[0]);

  sig_uncatch(sig_child);
  sig_unblock(sig_child);
  sig_uncatch(sig_term);
  sig_uncatch(sig_pipe);

  if (fcntl(sslctl[1],F_SETFD,0) == -1)
    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
  strnum[fmt_ulong(strnum,sslctl[1])]=0;
  env("SSLCTLFD",strnum);

  if (fcntl(pi[0],F_SETFD,0) == -1)
    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
  strnum[fmt_ulong(strnum,pi[0])]=0;
  env("SSLREADFD",strnum);

  if (fcntl(po[1],F_SETFD,0) == -1)
    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
  strnum[fmt_ulong(strnum,po[1])]=0;
  env("SSLWRITEFD",strnum);

  if (flagsslwait) {
    if (fd_copy(0,t) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 0: ");
    if (fd_copy(1,t) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 1: ");
  } else {
    if (fd_move(0,pi[0]) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 0: ");
    if (fd_move(1,po[1]) == -1)
      strerr_die2sys(111,DROP,"unable to set up descriptor 1: ");
  }

  if (flagkillopts)
    socket_ipoptionskill(t);
  if (!flagdelay)
    socket_tcpnodelay(t);

  if (*banner) {
    buffer_init(&b,buffer_unixwrite,1,bspace,sizeof bspace);
    if (buffer_putsflush(&b,banner) == -1)
      strerr_die2sys(111,DROP,"unable to print banner: ");
  }

  if (!flagsslwait) {
    ssl_cmd = flagsslenv ? 'Y' : 'y';
    if (write(sslctl[1], &ssl_cmd, 1) < 1)
      strerr_die2sys(111,DROP,"unable to start SSL: ");
    if (flagsslenv) {
      while ((j=read(sslctl[1],envbuf,8192)) > 0) {
        stralloc_catb(&ssl_env,envbuf,j);
        if (ssl_env.len >= 2 && ssl_env.s[ssl_env.len-2]==0 && ssl_env.s[ssl_env.len-1]==0)
          break;
      }
      if (j < 0)
        strerr_die2sys(111,DROP,"unable to read SSL environment: ");
      pathexec_multienv(&ssl_env);
    }
  }
      
  pathexec(prog);
  strerr_die4sys(111,DROP,"unable to run ",*prog,": ");
}
コード例 #2
0
ファイル: dns.c プロジェクト: clementdotck/moloch
void dns_parser(MolochSession_t *session, const unsigned char *data, int len) 
{

    if (len < 18)
        return;

    int qr      = (data[2] >> 7) & 0x1;
    int opcode  = (data[2] >> 3) & 0xf;

    if (opcode != 0)
        return;

    int qdcount = (data[4] << 8) | data[5];
    int ancount = (data[6] << 8) | data[7];

    if (qdcount > 10 || qdcount <= 0)
        return;

    BSB bsb;
    BSB_INIT(bsb, data + 12, len - 12);

    /* QD Section */
    int i;
    for (i = 0; BSB_NOT_ERROR(bsb) && i < qdcount; i++) {
        int namelen;
        unsigned char *name = dns_name(data, len, &bsb, &namelen);

        if (BSB_IS_ERROR(bsb))
            break;

        if (!namelen) {
            name = (unsigned char*)"<root>";
            namelen = 6;
        }

        unsigned short qtype = 0 , qclass = 0 ;
        BSB_IMPORT_u16(bsb, qtype);
        BSB_IMPORT_u16(bsb, qclass);

        char *lower = g_ascii_strdown((char*)name, namelen);

        if (qclass <= 255 && qclasses[qclass]) {
            moloch_field_string_add(queryClassField, session, qclasses[qclass], -1, TRUE);
        }

        if (qtype <= 255 && qtypes[qtype]) {
            moloch_field_string_add(queryTypeField, session, qtypes[qtype], -1, TRUE);
        }

        if (lower && !moloch_field_string_add(hostField, session, lower, namelen, FALSE)) {
            g_free(lower);
        }
    }
    moloch_nids_add_protocol(session, "dns");

    if (qr == 0)
        return;

    int rcode      = data[3] & 0xf;
    moloch_field_string_add(statusField, session, statuses[rcode], -1, TRUE);

    for (i = 0; BSB_NOT_ERROR(bsb) && i < ancount; i++) {
        int namelen;
        dns_name(data, len, &bsb, &namelen);

        if (BSB_IS_ERROR(bsb))
            break;

        uint16_t antype = 0;
        BSB_IMPORT_u16 (bsb, antype);
        uint16_t anclass = 0;
        BSB_IMPORT_u16 (bsb, anclass);
        BSB_IMPORT_skip(bsb, 4); // ttl
        uint16_t rdlength = 0;
        BSB_IMPORT_u16 (bsb, rdlength);

        if (BSB_REMAINING(bsb) < rdlength) {
            break;
        }

        if (anclass != 1) {
            BSB_IMPORT_skip(bsb, rdlength);
            continue;
        }

        switch (antype) {
        case 1: {
            if (rdlength != 4)
                break;
            struct in_addr in;
            unsigned char *ptr = BSB_WORK_PTR(bsb);
            in.s_addr = ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0];

            moloch_field_int_add(ipField, session, in.s_addr);
            break;
        }
        case 5: {
            BSB rdbsb;
            BSB_INIT(rdbsb, BSB_WORK_PTR(bsb), rdlength);

            int namelen;
            unsigned char *name = dns_name(data, len, &rdbsb, &namelen);

            if (!namelen || BSB_IS_ERROR(rdbsb))
                continue;

            char *lower = g_ascii_strdown((char*)name, namelen);

            if (lower && !moloch_field_string_add(hostField, session, lower, namelen, FALSE)) {
                g_free(lower);
            }
            break;
        }
        case 15: {
            BSB rdbsb;
            BSB_INIT(rdbsb, BSB_WORK_PTR(bsb), rdlength);
            BSB_IMPORT_skip(rdbsb, 2); // preference

            int namelen;
            unsigned char *name = dns_name(data, len, &rdbsb, &namelen);

            if (!namelen || BSB_IS_ERROR(rdbsb))
                continue;

            char *lower = g_ascii_strdown((char*)name, namelen);

            if (lower && !moloch_field_string_add(hostField, session, lower, namelen, FALSE)) {
                g_free(lower);
            }
        }
        } /* switch */
        BSB_IMPORT_skip(bsb, rdlength);
    }
}
コード例 #3
0
ファイル: qmail-tcpsrv.c プロジェクト: kp-org/eQmail
void doit(int t)
{
  int j;
  uint32 scope_id;

  if (ip6_isv4mapped(remoteip))
    remoteipstr[ip4_fmt(remoteipstr,remoteip+12)] = 0;
  else
    remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0;

  if (verbosity >= 2) {
    strnum[fmt_ulong(strnum,getpid())] = 0;
    log(B("pid ",strnum," from ",remoteipstr,0));
  }

  if (flagkillopts)
    socket_ipoptionskill(t);
  if (!flagdelay)
    socket_tcpnodelay(t);

  if (*banner) {
    buffer_init(&b,write,t,bspace,sizeof bspace);
    if (buffer_putsflush(&b,banner) == -1)
      errint(EHARD,"unable to print banner: ");
  }

  if (socket_local(t,localip,&localport,&scope_id) == -1)
    errint(EHARD,"unable to get local address: ");

  if (ip6_isv4mapped(localip))
    localipstr[ip4_fmt(localipstr,localip+12)] = 0;
  else
    localipstr[ip6_fmt(localipstr,localip)] = 0;
  remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0;

  if (!localhost)
    if (dns_name(&localhostsa,localip) == 0)
      if (localhostsa.len) {
    if (!stralloc_0(&localhostsa)) errmem;
    localhost = localhostsa.s;
      }
  env("PROTO","TCP");

  env("TCPLOCALIP",localipstr);
  env("TCPLOCALPORT",localportstr);
  env("TCPLOCALHOST",localhost);

  if (flagremotehost)
    if (dns_name(&remotehostsa,remoteip) == 0)
      if (remotehostsa.len) {
    if (flagparanoid)
      if (dns_ip6(&tmp,&remotehostsa) == 0)
        for (j = 0;j + 16 <= tmp.len;j += 16)
          if (byte_equal(remoteip,16,tmp.s + j)) {
        flagparanoid = 0;
        break;
          }
    if (!flagparanoid) {
      if (!stralloc_0(&remotehostsa)) errmem;
      remotehost = remotehostsa.s;
    }
      }
  env("TCPREMOTEIP",remoteipstr);
  env("TCPREMOTEPORT",remoteportstr);
  env("TCPREMOTEHOST",remotehost);

  if (flagremoteinfo) {
    if (remoteinfo6(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout,netif) == -1)
      flagremoteinfo = 0;
    if (!stralloc_0(&tcpremoteinfo)) errmem;
  }
  env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);

  if (fnrules) {
    int fdrules;
    fdrules = open_read(fnrules);
    if (fdrules == -1) {
      if (errno != error_noent) drop_rules();
      if (!flagallownorules) drop_rules();
    }
    else {
      char* temp;
	  if (ip6_isv4mapped(remoteip))
        temp=remoteipstr+7;
      else
        temp=remoteipstr;
      if (rules(found,fdrules,temp,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules();
      close(fdrules);
//      log(B("checking tcp rules for ",remotehost,": pass"));
    }
  }

  if (verbosity >= 2) {
    strnum[fmt_ulong(strnum,getpid())] = 0;
    if (!stralloc_copys(&tmp,"qmail-tcpsrv: ")) errmem;
    safecats(flagdeny ? "deny" : "ok");
    cats(" "); safecats(strnum);
    cats(" "); if (localhost) safecats(localhost);
    cats(":"); safecats(localipstr);
    cats(":"); safecats(localportstr);
    cats(" "); if (remotehost) safecats(remotehost);
    cats(":"); safecats(remoteipstr);
//    cats(":<remote info>"); if (flagremoteinfo) safecats(tcpremoteinfo.s);
    cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s);
    cats(":"); safecats(remoteportstr);
    cats("\n");
    buffer_putflush(buffer_2,tmp.s,tmp.len);
  }

  if (flagdeny) _exit(100);
}