| 34 | | void |
|---|
| 35 | | http_request(int sockfd, struct sockaddr_in their_addr) |
|---|
| 36 | | { |
|---|
| 37 | | char buffer[MAX_BUF], request[MAX_BUF]; |
|---|
| 38 | | char line[MAX_BUF], header[MAX_BUF]; |
|---|
| 39 | | char body[MAX_BUF]; |
|---|
| 40 | | char *token; |
|---|
| 41 | | void *p1, *p2; |
|---|
| 42 | | char *p3, *p4; |
|---|
| 43 | | int r_get = 0, r_token = 0, s, rc, profile; |
|---|
| 44 | | time_t cur_time; |
|---|
| 45 | | char *ip, *mac; |
|---|
| 46 | | |
|---|
| 47 | | cur_time = time(NULL); |
|---|
| 48 | | |
|---|
| 49 | | p1 = request; |
|---|
| 50 | | |
|---|
| 51 | | do { |
|---|
| 52 | | s = recv(sockfd, buffer, sizeof(buffer) - 1, 0); |
|---|
| 53 | | memcpy(p1, buffer, s); |
|---|
| 54 | | p1 += s; |
|---|
| 55 | | } while(!(p2 = strstr(request, "\r\n\r\n")) && s); |
|---|
| 56 | | request[(int)p2 - (int)request + 2] = '\0'; |
|---|
| 57 | | |
|---|
| 58 | | if ((p1 = strstr(request, "\r\n"))) { |
|---|
| 59 | | memcpy(line, request, (int)p1 - (int)request); |
|---|
| 60 | | line[(int)p1 - (int)request] = '\0'; |
|---|
| 61 | | if ((strncasecmp(line, "GET", 3) == 0) || |
|---|
| 62 | | (strncasecmp(line, "POST", 4) == 0) || |
|---|
| 63 | | (strncasecmp(line, "HEAD", 4) == 0)) { |
|---|
| 64 | | r_get = 1; |
|---|
| 65 | | if (strstr(line, "/auth") && (p3 = strchr(line, '?')) != NULL) { |
|---|
| 66 | | if ((p4 = strchr(p3, ' '))) { |
|---|
| 67 | | p4[0] = '\0'; |
|---|
| 68 | | } |
|---|
| 69 | | if ((p4 = strchr(p3, '\n'))) { |
|---|
| 70 | | p4[0] = '\0'; |
|---|
| 71 | | } |
|---|
| 72 | | init_cgi(p3 + 1); |
|---|
| 73 | | if ((token = get_cgi("token")) && (strlen(token) > 0)) { |
|---|
| 74 | | r_token = 1; |
|---|
| 75 | | } |
|---|
| 76 | | } |
|---|
| 77 | | } |
|---|
| 78 | | } |
|---|
| 79 | | |
|---|
| 80 | | if (r_get && r_token) { |
|---|
| 81 | | ip = inet_ntoa(their_addr.sin_addr); |
|---|
| 82 | | mac = arp_get(ip); |
|---|
| 83 | | |
|---|
| 84 | | /* We will respond with a 200 all the time */ |
|---|
| 85 | | http_header(header, 200, "OK", NULL); |
|---|
| 86 | | |
|---|
| 87 | | if (!mac) { |
|---|
| 88 | | http_body(body, "I could not find your hardware address for your IP address %s, please report this error to the systems administrator", ip); |
|---|
| 89 | | } else { |
|---|
| 90 | | if ((profile = authenticate(ip, mac, token, 0)) != -1) { |
|---|
| 91 | | /* Authentication succesful */ |
|---|
| 92 | | if (profile == 0) { |
|---|
| 93 | | http_body(body, "This token is not valid anymore"); |
|---|
| 94 | | } else { |
|---|
| 95 | | if ((rc = fw_allow(ip, mac, profile)) == 0) { |
|---|
| 96 | | http_body(body, "You %s at %s, have been granted profile %d!", ip, mac, profile); |
|---|
| 97 | | |
|---|
| 98 | | /* Add client's IP and token into a linked list so we can keep |
|---|
| 99 | | * track of it on the auth server, only if he's not there already */ |
|---|
| 100 | | if (!node_find_by_ip(ip)) { |
|---|
| 101 | | node_add(ip, mac, token, 0); |
|---|
| 102 | | } |
|---|
| 103 | | } else { |
|---|
| 104 | | http_body(body, "Authentication was succesful, but the firewall could not be modified, I got return code %d, please contact the systems administrators"); |
|---|
| 105 | | } |
|---|
| 106 | | } |
|---|
| 107 | | } else { |
|---|
| 108 | | /* Authentication unsuccesful */ |
|---|
| 109 | | http_body(body, "Access denied because we did not get a valid answer from the authentication server"); |
|---|
| 110 | | } |
|---|
| 111 | | } |
|---|
| 112 | | } else if (r_get) { |
|---|
| 113 | | char newlocation[MAX_BUF]; |
|---|
| 114 | | sprintf(newlocation, "%s?gw_address=%s&gw_port=%d&gw_id=%s", config.authserv_loginurl, config.gw_address, config.gw_port, config.gw_id); |
|---|
| 115 | | |
|---|
| 116 | | /* If we got a GET/POST/HEAD but no token, redirect */ |
|---|
| 117 | | http_header(header, 302, "Found", "Location: %s", newlocation); |
|---|
| 118 | | http_body(body, "This document has moved <a href=\"%s\">here</a>", newlocation); |
|---|
| 119 | | debug(D_LOG_INFO, "302 - %s - %s", inet_ntoa(their_addr.sin_addr), newlocation); |
|---|
| 120 | | } else { |
|---|
| 121 | | /* Else, error page */ |
|---|
| 122 | | http_header(header, 500, "Error", NULL); |
|---|
| 123 | | http_body(body, "I could not understand your request"); |
|---|
| 124 | | debug(D_LOG_INFO, "500 - %s", inet_ntoa(their_addr.sin_addr)); |
|---|
| 125 | | } |
|---|
| 126 | | sock_send(sockfd, header); |
|---|
| 127 | | sock_send(sockfd, body); |
|---|
| 128 | | |
|---|
| 129 | | debug(D_LOG_INFO, "Closing connection to %s", inet_ntoa(their_addr.sin_addr)); |
|---|
| 130 | | close(sockfd); |
|---|
| 131 | | //fixme |
|---|
| 132 | | //FD_CLR(sockfd, &master); |
|---|
| 133 | | } |
|---|
| 134 | | |
|---|
| 135 | | void |
|---|
| 136 | | http_header(char *buffer, int code, char *code_msg, char *fmt, ...) |
|---|
| 137 | | { |
|---|
| 138 | | va_list ap; |
|---|
| 139 | | char tmp[MAX_BUF]; |
|---|
| 140 | | |
|---|
| 141 | | sprintf(buffer, "HTTP/1.1 %d %s\n", code, code_msg); |
|---|
| 142 | | sprintf(tmp, "Server: %s\n", config.httpdname); |
|---|
| 143 | | strcat(buffer, tmp); |
|---|
| 144 | | sprintf(tmp, "Date: %s\n", gmtdate()); |
|---|
| 145 | | strcat(buffer, tmp); |
|---|
| 146 | | |
|---|
| 147 | | if (fmt) { |
|---|
| 148 | | va_start(ap, fmt); |
|---|
| 149 | | vsprintf(tmp, fmt, ap); |
|---|
| 150 | | va_end(ap); |
|---|
| 151 | | strcat(buffer, tmp); |
|---|
| 152 | | strcat(buffer, "\n"); |
|---|
| 153 | | } |
|---|
| 154 | | |
|---|
| 155 | | strcat(buffer, "Content-Type: text/html\n"); |
|---|
| 156 | | strcat(buffer, "Connection: close\n\n"); |
|---|
| 157 | | } |
|---|
| 158 | | |
|---|
| 159 | | void |
|---|
| 160 | | http_body(char *body, char *fmt, ...) |
|---|
| 161 | | { |
|---|
| 162 | | va_list ap; |
|---|
| 163 | | char tmp[MAX_BUF]; |
|---|
| 164 | | |
|---|
| 165 | | strcpy(body, "<HTML><HEAD></HEAD><BODY>"); |
|---|
| 166 | | |
|---|
| 167 | | va_start(ap, fmt); |
|---|
| 168 | | vsprintf(tmp, fmt, ap); |
|---|
| 169 | | va_end(ap); |
|---|
| 170 | | |
|---|
| 171 | | strcat(body, tmp); |
|---|
| 172 | | strcat(body, "</BODY></HTML>\n\n"); |
|---|
| 173 | | } |
|---|
| 174 | | |
|---|
| 175 | | void |
|---|
| 176 | | sock_send(int sockfd, char *buffer) |
|---|
| 177 | | { |
|---|
| 178 | | send(sockfd, buffer, strlen(buffer), 0); |
|---|
| 179 | | } |
|---|
| 180 | | |
|---|
| 181 | | char * |
|---|
| 182 | | gmtdate() |
|---|
| 183 | | { |
|---|
| 184 | | char *strdate; |
|---|
| 185 | | time_t rawtime; |
|---|
| 186 | | struct tm *tmtime; |
|---|
| 187 | | |
|---|
| 188 | | strdate = (char *)malloc(255); |
|---|
| 189 | | |
|---|
| 190 | | time(&rawtime); |
|---|
| 191 | | tmtime = gmtime(&rawtime); |
|---|
| 192 | | strftime(strdate, 255, "%a, %d %b %Y %T %Z", tmtime); |
|---|
| 193 | | |
|---|
| 194 | | return strdate; |
|---|
| | 36 | if (asprintf(&newlocation, "Location: %s?gw_address=%s&gw_port=%d&gw_id=%s", config.authserv_loginurl, config.gw_address, config.gw_port, config.gw_id) == -1) { |
|---|
| | 37 | debug(D_LOG_ERR, "Failed to asprintf newlocation"); |
|---|
| | 38 | httpdOutput(webserver, "Internal error occurred"); |
|---|
| | 39 | } |
|---|
| | 40 | else { |
|---|
| | 41 | // Re-direct them to auth server |
|---|
| | 42 | httpdSetResponse(webserver, "307 Please authenticate yourself here"); |
|---|
| | 43 | httpdAddHeader(webserver, newlocation); |
|---|
| | 44 | httpdPrintf(webserver, "<html><head>Redirection</head><body>Please <a href='%s?gw_address=%s&gw_port=%d&gw_id=%s'>click here</a> to login", config.authserv_loginurl, config.gw_address, config.gw_port, config.gw_id); |
|---|
| | 45 | debug(D_LOG_INFO, "Captured %s and re-directed them to login page", webserver->clientAddr); |
|---|
| | 46 | free(newlocation); |
|---|
| | 47 | } |
|---|
| | 59 | void http_callback_auth(httpd * webserver) |
|---|
| | 60 | { |
|---|
| | 61 | httpVar * token; |
|---|
| | 62 | char * mac; |
|---|
| | 63 | int profile; |
|---|
| | 64 | int temp; |
|---|
| | 65 | |
|---|
| | 66 | if (token = httpdGetVariableByName(webserver, "token")) { |
|---|
| | 67 | // They supplied variable "token" |
|---|
| | 68 | if (!(mac = arp_get(webserver->clientAddr))) { |
|---|
| | 69 | // We could not get their MAC address |
|---|
| | 70 | debug(D_LOG_ERR, "Failed to retrieve MAC address for ip %s", webserver->clientAddr); |
|---|
| | 71 | httpdOutput(webserver, "Failed to retrieve your MAC address"); |
|---|
| | 72 | } |
|---|
| | 73 | else { |
|---|
| | 74 | // We have their MAC address |
|---|
| | 75 | profile = authenticate(webserver->clientAddr, mac, token->value, 0); |
|---|
| | 76 | if (profile == -1) { |
|---|
| | 77 | // Error talking to central server |
|---|
| | 78 | debug(D_LOG_ERR, "Got %d from central server authenticating token %s from %s at %s", profile, token->value, webserver->clientAddr, mac); |
|---|
| | 79 | httpdOutput(webserver, "Access denied: We did not get a valid answer from the central server"); |
|---|
| | 80 | } |
|---|
| | 81 | else if (profile == 0) { |
|---|
| | 82 | // Central server said invalid token |
|---|
| | 83 | httpdOutput(webserver, "Your authentication has failed or timed-out. Please re-login"); |
|---|
| | 84 | } |
|---|
| | 85 | else { |
|---|
| | 86 | // Central server says token's good |
|---|
| | 87 | // Now we should let them in |
|---|
| | 88 | temp = fw_allow(webserver->clientAddr, mac, profile); |
|---|
| | 89 | if (temp == 0) { |
|---|
| | 90 | // They were added to firewall a-ok |
|---|
| | 91 | /* Add client's IP and token into a linked list so we can keep |
|---|
| | 92 | * track of it on the auth server, only if he's not there already */ |
|---|
| | 93 | if (!node_find_by_ip(webserver->clientAddr)) { |
|---|
| | 94 | node_add(webserver->clientAddr, mac, token->value, 0); |
|---|
| | 95 | } |
|---|
| | 96 | } |
|---|
| | 97 | else { |
|---|
| | 98 | debug(D_LOG_ERR, "fw_allow returned %d when giving %s at %s profile %d", temp, webserver->clientAddr, mac, profile); |
|---|
| | 99 | httpdOutput(webserver, "Authentication succeeded, however we failed to modify the firewall."); |
|---|
| | 100 | } |
|---|
| | 101 | } |
|---|
| | 102 | free(mac); |
|---|
| | 103 | } |
|---|
| | 104 | } |
|---|
| | 105 | else { |
|---|
| | 106 | // They did not supply variable "token" |
|---|
| | 107 | httpdOutput(webserver, "Invalid token"); |
|---|
| | 108 | } |
|---|
| | 109 | } |
|---|
| | 110 | |
|---|