Exemplo n.º 1
0
static int smtp_server(CLI *c) {
    char line[STRLEN];

    if(RFC2487(c, c->local_rfd.fd)==0)
        return 0; /* Return if RFC 2487 is not used */

    if(fdscanf(c, c->remote_fd.fd, "220%[^\n]", line)!=1) {
        s_log(LOG_ERR, "Unknown server welcome");
        return -1;
    }
    if(fdprintf(c, c->local_wfd.fd, "220%s + stunnel", line)<0)
        return -1;
    if(fdscanf(c, c->local_rfd.fd, "EHLO %[^\n]", line)!=1) {
        s_log(LOG_ERR, "Unknown client EHLO");
        return -1;
    }
    if(fdprintf(c, c->local_wfd.fd, "250-%s Welcome", line)<0)
        return -1;
    if(fdprintf(c, c->local_wfd.fd, "250 STARTTLS")<0)
        return -1;
    if(fdscanf(c, c->local_rfd.fd, "STARTTLS", line)<0) {
        s_log(LOG_ERR, "STARTTLS expected");
        return -1;
    }
    if(fdprintf(c, c->local_wfd.fd, "220 Go ahead")<0)
        return -1;
    return 0;
}
Exemplo n.º 2
0
static int smtp_client(CLI *c) {
    char line[STRLEN];
    
    do { /* Copy multiline greeting */
        if(fdscanf(c, c->remote_fd.fd, "%[^\n]", line)<0)
            return -1;
        if(fdprintf(c, c->local_wfd.fd, "%s", line)<0)
            return -1;
    } while(strncasecmp(line,"220-",4)==0);

    if(fdprintf(c, c->remote_fd.fd, "EHLO localhost")<0) /* Send an EHLO command */
        return -1;
    do { /* Skip multiline reply */
        if(fdscanf(c, c->remote_fd.fd, "%[^\n]", line)<0)
            return -1;
    } while(strncasecmp(line,"250-",4)==0);
    if(strncasecmp(line,"250 ",4)!=0) { /* Error */
        s_log(LOG_ERR, "Remote server is not RFC 1425 compliant");
        return -1;
    }

    if(fdprintf(c, c->remote_fd.fd, "STARTTLS")<0) /* Send STARTTLS command */
        return -1;
    do { /* Skip multiline reply */
        if(fdscanf(c, c->remote_fd.fd, "%[^\n]", line)<0)
            return -1;
    } while(strncasecmp(line,"220-",4)==0);
    if(strncasecmp(line,"220 ",4)!=0) { /* Error */
        s_log(LOG_ERR, "Remote server is not RFC 2487 compliant");
        return -1;
    }
    return 0;
}
Exemplo n.º 3
0
static int auth_user(CLI *c) {
    struct servent *s_ent;    /* structure for getservbyname */
    SOCKADDR_UNION ident;     /* IDENT socket name */
    int fd;                   /* IDENT socket descriptor */
    char name[STRLEN];
    int retval;
    int error;

    if(!c->opt->username)
        return 0; /* -u option not specified */
    if((fd=socket(c->peer_addr.addr[0].sa.sa_family, SOCK_STREAM, 0))<0) {
        sockerror("socket (auth_user)");
        return -1;
    }
    if(alloc_fd(fd))
        return -1;
    memcpy(&ident, &c->peer_addr.addr[0], sizeof(SOCKADDR_UNION));
    s_ent=getservbyname("auth", "tcp");
    if(s_ent) {
        ident.in.sin_port=s_ent->s_port;
    } else {
        s_log(LOG_WARNING, "Unknown service 'auth': using default 113");
        ident.in.sin_port=htons(113);
    }
    if(connect(fd, &ident.sa, addr_len(ident))) {
        error=get_last_socket_error();
        if(error!=EINPROGRESS && error!=EWOULDBLOCK) {
            sockerror("ident connect (auth_user)");
            closesocket(fd);
            return -1;
        }
        if(connect_wait(c, fd, c->opt->timeout_connect)) { /* error */
            closesocket(fd);
            return -1;
        }
    }
    s_log(LOG_DEBUG, "IDENT server connected");
    if(fdprintf(c, fd, "%u , %u",
            ntohs(c->peer_addr.addr[0].in.sin_port),
            ntohs(c->opt->local_addr.addr[0].in.sin_port))<0) {
        sockerror("fdprintf (auth_user)");
        closesocket(fd);
        return -1;
    }
    if(fdscanf(c, fd, "%*[^:]: USERID :%*[^:]:%s", name)!=1) {
        s_log(LOG_ERR, "Incorrect data from IDENT server");
        closesocket(fd);
        return -1;
    }
    closesocket(fd);
    retval=strcmp(name, c->opt->username) ? -1 : 0;
    safestring(name);
    s_log(LOG_INFO, "IDENT resolved remote user to %s", name);
    return retval;
}
Exemplo n.º 4
0
static int nntp_client(CLI *c) {
    char line[STRLEN];

    if(fdscanf(c, c->remote_fd.fd, "%[^\n]", line)<0)
        return -1;
    if(strncasecmp(line,"200 ",4) && strncasecmp(line,"201 ",4)) {
        s_log(LOG_ERR, "Unknown server welcome");
        return -1;
    }
    if(fdprintf(c, c->local_wfd.fd, "%s", line)<0)
        return -1;
    if(fdprintf(c, c->remote_fd.fd, "STARTTLS")<0)
        return -1;
    if(fdscanf(c, c->remote_fd.fd, "%[^\n]", line)<0)
        return -1;
    if(strncasecmp(line,"382 ",4)) {
        s_log(LOG_ERR, "Server does not support TLS");
        return -1;
    }
    return 0;
}
Exemplo n.º 5
0
static int pop3_server(CLI *c) {
    char line[STRLEN];

    if(fdscanf(c, c->remote_fd.fd, "%[^\n]", line)<0)
        return -1;
    if(fdprintf(c, c->local_wfd.fd, "%s + stunnel", line)<0)
        return -1;
    if(fdscanf(c, c->local_rfd.fd, "%[^\n]", line)<0)
        return -1;
    if(!strncasecmp(line, "CAPA", 4)) { /* Client wants RFC 2449 extensions */
        if(fdprintf(c, c->local_wfd.fd, "-ERR Stunnel does not support capabilities")<0)
            return -1;
        if(fdscanf(c, c->local_rfd.fd, "%[^\n]", line)<0)
            return -1;
    }
    if(strncasecmp(line, "STLS", 4)) {
        s_log(LOG_ERR, "Client does not want TLS");
        return -1;
    }
    if(fdprintf(c, c->local_wfd.fd, "+OK Stunnel starts TLS negotiation")<0)
        return -1;

    return 0;
}
Exemplo n.º 6
0
static int auth_user(CLI *c) {
    struct servent *s_ent;    /* structure for getservbyname */
    struct sockaddr_in ident; /* IDENT socket name */
    int fd;                   /* IDENT socket descriptor */
    char name[STRLEN];
    int retval;

    if(!c->opt->username)
        return 0; /* -u option not specified */
    if((fd=socket(AF_INET, SOCK_STREAM, 0))<0) {
        sockerror("socket (auth_user)");
        return -1;
    }
    alloc_fd(fd);
    memcpy(&ident, &c->addr, sizeof(ident));
    s_ent=getservbyname("auth", "tcp");
    if(!s_ent) {
        log(LOG_WARNING, "Unknown service 'auth': using default 113");
        ident.sin_port=htons(113);
    } else {
        ident.sin_port=s_ent->s_port;
    }
    if(connect(fd, (struct sockaddr *)&ident, sizeof(ident))<0) {
        switch(get_last_socket_error()) {
        case EINPROGRESS: /* retry */
            log(LOG_DEBUG, "connect #1 (auth_user): EINPROGRESS: retrying");
            break;
        case EWOULDBLOCK: /* retry */
            log(LOG_DEBUG, "connect #1 (auth_user): EWOULDBLOCK: retrying");
            break;
        default:
            sockerror("connect #1 (auth_user)");
            closesocket(fd);
            return -1;
        }
        if(waitforsocket(fd, 1 /* write */, c->opt->timeout_busy)<1) {
            closesocket(fd);
            return -1;
        }
        if(connect(fd, (struct sockaddr *)&ident, sizeof(ident))<0) {
            switch(get_last_socket_error()) {
            case EINVAL: /* WIN32 is strange... */
                log(LOG_DEBUG, "connect #2 (auth_user): EINVAL: ok");
            case EISCONN: /* ok */
                break; /* success */
            default:
                sockerror("connect #2 (auth_user))");
                closesocket(fd);
                return -1;
            }
        }
    }
    log(LOG_DEBUG, "IDENT server connected");
    if(fdprintf(c, fd, "%u , %u",
            ntohs(c->addr.sin_port), ntohs(c->opt->localport))<0) {
        sockerror("fdprintf (auth_user)");
        closesocket(fd);
        return -1;
    }
    if(fdscanf(c, fd, "%*[^:]: USERID :%*[^:]:%s", name)!=1) {
        log(LOG_ERR, "Incorrect data from IDENT server");
        closesocket(fd);
        return -1;
    }
    closesocket(fd);
    retval=strcmp(name, c->opt->username) ? -1 : 0;
    safestring(name);
    log(LOG_INFO, "IDENT resolved remote user to %s", name);
    return retval;
}