int try_connect_HELO(const char *hostname) { char dbg_hostname[BIG_BUF]; char dbg_version[BIG_BUF]; char buf[BIG_BUF]; char testme[BIG_BUF]; /* Try the HELO protocal */ if(my_socket != -1) sock_close(my_socket); if (sock_open(get_string("mailserver"), get_number("smtp-socket", 25), &my_socket)) return 0; if (sock_readline(my_socket, buf, sizeof(buf)) == 0) return 0; if(!sscanf(buf,"220 %s %s", &dbg_hostname[0], &dbg_version[0])) return 0; log_printf(9, "Connected: %s (%s)\n", dbg_hostname, dbg_version); sock_printf(my_socket, "HELO %s\r\n", hostname); if(sock_readline(my_socket, buf, sizeof(buf)) == 0) return 0; if(!sscanf(buf, "250 %s", testme)) return 0; return 1; }
/* * reads in an entire message from the ftp server. */ char *read_sock(int sock) { char ibuf[8192], *bigbuf = NULL; int r; unsigned int total = 0; for(;;) { memset(ibuf, 0x0, sizeof(ibuf)); r = sock_readline(sock, ibuf, sizeof(ibuf) - 1); bigbuf = Realloc(bigbuf, (total + strlen(ibuf) + 1) * sizeof(char)); memcpy(bigbuf + total, ibuf, strlen(ibuf)); bigbuf[total + strlen(ibuf)] = 0x0; total += strlen(ibuf); if(strlen(ibuf) < 4) break; /* multi-lined responses have a dash as the 4th character */ if(ibuf[3] != '-') break; } if(debug_read) { printf(" < %s", bigbuf); fflush(stdout); } return bigbuf; }
int try_connect_EHLO(const char *hostname) { char dbg_hostname[BIG_BUF]; char dbg_version[BIG_BUF]; char buf[BIG_BUF]; char testme[BIG_BUF]; int read_data = 0; if(my_socket != -1) sock_close(my_socket); log_printf(9, "Attempting to connect to %s\n", get_string("mailserver")); if (sock_open(get_string("mailserver"), get_number("smtp-socket", 25), &my_socket)) return 0; while(sock_readline(my_socket, buf, sizeof(buf)) != 0) { int val; char ch; read_data = 1; log_printf(9,"Server sent: %s\n", buf); sscanf(buf, "%d%c%s %s", &val, &ch, &dbg_hostname[0], &dbg_version[0]); if(val != 220) { return 0; } if(ch != '-') { log_printf(9, "Connected: %s (%s)\n", dbg_hostname, dbg_version); break; } } if(!read_data) return 0; sock_printf(my_socket, "EHLO %s\r\n", hostname); if(sock_readline(my_socket, buf, sizeof(buf)) == 0) return 0; /* Check for valid response */ if(!sscanf(buf, "250-%s", testme)) return 0; /* Okay, we have a valid ESMTP server. Read the server caps */ while(sock_readline(my_socket, buf, sizeof(buf)) != 0) { int val; char ch; log_printf(9,"Server sent: %s\n", buf); sscanf(buf, "%d%c%s", &val, &ch, testme); if(val != 250) { return 0; } if(ch != '-') break; else { if (!strcmp(testme,"DSN")) { servercaps &= CAPS_DSN; log_printf(9, "Server caps: server supports DSN\n"); } else if (!strcmp(testme,"8BITMIME")) { servercaps &= CAPS_MIME; log_printf(9, "Server caps: server supports MIME\n"); } } } return 1; }
// main check password function which do real job of authentication against dovecot static authn_status check_password(request_rec * r, const char *user, const char *password) { authn_dovecot_config_rec *conf = ap_get_module_config(r->per_dir_config, &authn_dovecot_module); apr_pool_t *p; // sub pool of r->pool int i, auths, readsocks, result, opts, fdmax, cnt, auth_in_progress, retval; struct sockaddr_un address; struct timeval tv; struct connection_state cs; apr_pool_create(&p, r->pool); // create subpool for local functions, variables... // setting default values for connection state cs.version_ok = 0; cs.mech_available = 0; cs.hshake_done = 0; cs.authenticated = 0; // by default user is NOT authenticated :) cs.handshake_sent = 0; cs.user = NULL; fd_set socks_r; fd_set socks_w; fd_set error_fd; char * const line = apr_pcalloc(p, sizeof(char) * (BUFFMAX + 1)); ap_assert(line != NULL); auths = socket(AF_UNIX, SOCK_STREAM, 0); opts = fcntl(auths, F_GETFL); opts = (opts | O_NONBLOCK); if (fcntl(auths, F_SETFL, opts) < 0) { perror("fcntl(F_SETFL)"); } address.sun_family = AF_UNIX; strncpy(address.sun_path,conf->dovecotauthsocket, strlen(conf->dovecotauthsocket)); result = connect(auths, (struct sockaddr *)&address, sizeof address); if (result) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: could not connect to dovecot socket"); if (conf->authoritative == 0) { return DECLINED; } else { return AUTH_USER_NOT_FOUND; } } cnt = 0; auth_in_progress = 0; // loop trough sockets for writability and for data on socket to read, // wait untill authenticated or if timeoout occurs error out with AUTH_USER_NOT_FOUND and log it while (cnt < conf->dovecotauthtimeout) { fdmax = auths; // simply this is only one really used socket so ... tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&socks_r); FD_SET(auths, &socks_r); FD_ZERO(&error_fd); FD_SET(auths, &error_fd); if (cs.handshake_sent == 0) { FD_ZERO(&socks_w); FD_SET(auths, &socks_w); } else { FD_ZERO(&socks_w); } readsocks = select(fdmax + 1, &socks_r, &socks_w, NULL, &tv); if (readsocks < 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: socket select"); return DECLINED; } if (readsocks == 0) { cnt++; // wait for timeout and count to conf->dovecotauthtimeout // only add to counter in case of timeout! //fprintf(stderr, "%i ", cnt); fflush(stdout); } else { for (i = 0; i <= fdmax; i++) { if (FD_ISSET(i, &socks_w)) { if (cs.handshake_sent == 0) { cs.handshake_sent = send_handshake(p, r, i); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Dovecot Authentication: handshake is sent"); } } if (FD_ISSET(i, &socks_r)) { while ((retval = sock_readline(p, r, i, line)) > 0) { if (!receive_data(p, r, &cs, line)) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Dovecot Authentication: problems while receiving data from socket"); if (conf->authoritative == 0) { return DECLINED; } else { return AUTH_USER_NOT_FOUND; } } else { if (cs.hshake_done == 1) { if (!cs.version_ok && !cs.mech_available) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: No authentication possible protocol version wrong or plaintext method not available..."); close(auths); return AUTH_USER_NOT_FOUND; } else { if (auth_in_progress != 1) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Dovecot Authentication: Sending authentication request"); send_auth_request(p, r, i, user, password, #if MODULE_MAGIC_NUMBER_MAJOR >= 20120211 r->connection->client_ip #else r->connection->remote_ip #endif ); auth_in_progress = 1; } } } if (cs.authenticated == 1) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Dovecot Authentication: Authenticated user=\"%s\"", user); close(auths); if (cs.user != NULL) { r->user = cs.user; } return AUTH_GRANTED; } if (cs.authenticated == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: Denied authentication for user=\"%s\"", user); close(auths); if (conf->authoritative == 0) { return DECLINED; } else { return AUTH_USER_NOT_FOUND; } } break; } } if (retval == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: socket reading failed bailing out"); close(auths); if (conf->authoritative == 0) { return DECLINED; } else { return AUTH_USER_NOT_FOUND; } } } } } } close(auths); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication Timeout"); if (conf->authoritative == 0) { return DECLINED; } else { return AUTH_USER_NOT_FOUND; } }