00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "nufw.h"
00024
00025 #include <nubase.h>
00026
00027
00028 pthread_mutex_t ipq_mutex = PTHREAD_MUTEX_INITIALIZER;
00029
00040 int auth_process_answer(char *dgram, int dgram_size)
00041 {
00042 nuv4_nuauth_decision_response_t *answer;
00043 uint32_t nfmark;
00044 int sandf;
00045 u_int32_t packet_id;
00046 int payload_len;
00047
00048
00049 if (dgram_size < (int) sizeof(nuv4_nuauth_decision_response_t)) {
00050 return -1;
00051 }
00052 answer = (nuv4_nuauth_decision_response_t *) dgram;
00053
00054
00055 payload_len = ntohs(answer->payload_len);
00056 if (dgram_size <
00057 (int) (sizeof(nuv4_nuauth_decision_response_t) + payload_len)
00058 || ((payload_len != 0) && (payload_len != (20 + 8))
00059 && (payload_len != (40 + 8)))) {
00060 log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_WARNING,
00061 "[!] Packet with improper size");
00062 return -1;
00063 }
00064
00065
00066 packet_id = ntohl(answer->packet_id);
00067
00068
00069 pthread_mutex_lock(&packets_list.mutex);
00070 sandf = psearch_and_destroy(packet_id, &nfmark);
00071 pthread_mutex_unlock(&packets_list.mutex);
00072 if (!sandf) {
00073 log_area_printf(DEBUG_AREA_GW | DEBUG_AREA_GW,
00074 DEBUG_LEVEL_WARNING,
00075 "[!] Packet without a known ID: %u",
00076 packet_id);
00077 return -1;
00078 }
00079
00080 switch (answer->decision) {
00081 case DECISION_ACCEPT:
00082
00083 debug_log_printf(DEBUG_AREA_PACKET,
00084 DEBUG_LEVEL_VERBOSE_DEBUG,
00085 "(*) Accepting packet with id=%u",
00086 packet_id);
00087 #if HAVE_LIBIPQ_MARK || USE_NFQUEUE
00088 if (nufw_set_mark) {
00089 debug_log_printf(DEBUG_AREA_PACKET,
00090 DEBUG_LEVEL_VERBOSE_DEBUG,
00091 "(*) Marking packet with %d",
00092 ntohl(answer->tcmark));
00093 IPQ_SET_VWMARK(packet_id, NF_ACCEPT,
00094 answer->tcmark);
00095 } else {
00096 IPQ_SET_VERDICT(packet_id, NF_ACCEPT);
00097 }
00098 #else
00099 IPQ_SET_VERDICT(packet_id, NF_ACCEPT);
00100 #endif
00101 pckt_tx++;
00102 break;
00103
00104 case DECISION_REJECT:
00105
00106 log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_VERBOSE_DEBUG,
00107 "(*) Rejecting %" PRIu32, packet_id);
00108 IPQ_SET_VERDICT(packet_id, NF_DROP);
00109 if (send_icmp_unreach(dgram +
00110 sizeof(nuv4_nuauth_decision_response_t)) == -1) {
00111 log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_WARNING,
00112 "(*) Could not sent ICMP reject for %" PRIu32, packet_id);
00113 }
00114 break;
00115
00116 default:
00117
00118 debug_log_printf(DEBUG_AREA_PACKET,
00119 DEBUG_LEVEL_VERBOSE_DEBUG,
00120 "(*) Drop packet %u", packet_id);
00121 IPQ_SET_VERDICT(packet_id, NF_DROP);
00122 }
00123 return sizeof(nuv4_nuauth_decision_response_t) + payload_len;
00124 }
00125
00126 #ifdef HAVE_LIBCONNTRACK
00127
00128 int build_nfct_tuple_from_message(struct nfct_tuple *orig,
00129 struct nuv4_conntrack_message_t
00130 *packet_hdr)
00131 {
00132 orig->protonum = packet_hdr->ip_protocol;
00133 if (is_ipv4(&packet_hdr->ip_src) && is_ipv4(&packet_hdr->ip_dst)) {
00134 orig->l3protonum = AF_INET;
00135 orig->src.v4 = packet_hdr->ip_src.s6_addr32[3];
00136 orig->dst.v4 = packet_hdr->ip_dst.s6_addr32[3];
00137 } else {
00138 orig->l3protonum = AF_INET6;
00139 memcpy(&orig->src.v6, &packet_hdr->ip_src,
00140 sizeof(orig->src.v6));
00141 memcpy(&orig->dst.v6, &packet_hdr->ip_dst,
00142 sizeof(orig->dst.v6));
00143 }
00144
00145 switch (packet_hdr->ip_protocol) {
00146 case IPPROTO_TCP:
00147 orig->l4src.tcp.port = packet_hdr->src_port;
00148 orig->l4dst.tcp.port = packet_hdr->dest_port;
00149 break;
00150 case IPPROTO_UDP:
00151 orig->l4src.udp.port = packet_hdr->src_port;
00152 orig->l4dst.udp.port = packet_hdr->dest_port;
00153 break;
00154 default:
00155 return 0;
00156 }
00157 return 1;
00158
00159 }
00160
00164 int auth_process_conn_destroy(char *dgram, int dgram_size)
00165 {
00166 struct nuv4_conntrack_message_t *packet_hdr;
00167 struct nfct_tuple orig;
00168 int id = 0;
00169
00170
00171 if (dgram_size < (int) sizeof(struct nuv4_conntrack_message_t)) {
00172 return -1;
00173 }
00174
00175 packet_hdr = (struct nuv4_conntrack_message_t *) dgram;
00176
00177 if (ntohs(packet_hdr->msg_length) != sizeof(struct nuv4_conntrack_message_t)) {
00178 return -1;
00179 }
00180
00181 if (build_nfct_tuple_from_message(&orig, packet_hdr)) {
00182 debug_log_printf(DEBUG_AREA_GW | DEBUG_AREA_PACKET,
00183 DEBUG_LEVEL_VERBOSE_DEBUG,
00184 "Deleting entry from conntrack after NuAuth request");
00185 (void) nfct_delete_conntrack(cth, &orig, NFCT_DIR_ORIGINAL,
00186 id);
00187 }
00188 return ntohs(packet_hdr->msg_length);
00189 }
00190
00194 int auth_process_conn_update(char *dgram, int dgram_size)
00195 {
00196 struct nuv4_conntrack_message_t *packet_hdr;
00197 struct nfct_conntrack *ct;
00198 struct nfct_tuple orig;
00199 struct nfct_tuple reply;
00200 union nfct_protoinfo proto;
00201
00202
00203
00204 if (dgram_size < (int) sizeof(struct nuv4_conntrack_message_t)) {
00205 debug_log_printf(DEBUG_AREA_GW, DEBUG_LEVEL_DEBUG,
00206 "NuAuth sent too small message");
00207 return -1;
00208 }
00209 packet_hdr = (struct nuv4_conntrack_message_t *) dgram;
00210
00211 if (ntohs(packet_hdr->msg_length) != sizeof(struct nuv4_conntrack_message_t)) {
00212 return -1;
00213 }
00214
00215 if (build_nfct_tuple_from_message(&orig, packet_hdr)) {
00216
00217 memset(&reply, 0, sizeof(reply));
00218 reply.l3protonum = orig.l3protonum;
00219 #if 0
00220
00221 memset(&reply.src, 0, sizeof(reply.src));
00222 memset(&reply.dst, 0, sizeof(reply.dst));
00223
00224 memset(&reply.l4src, 0, sizeof(reply.l4src));
00225 memset(&reply.l4dst, 0, sizeof(reply.l4dst));
00226 #endif
00227
00228
00229 proto.tcp.state = 3;
00230
00231 #ifdef HAVE_LIBCONNTRACK_FIXEDTIMEOUT
00232 ct = nfct_conntrack_alloc(&orig, &reply, 0,
00233 &proto,
00234 IPS_ASSURED | IPS_SEEN_REPLY |
00235 IPS_FIXED_TIMEOUT, 0, 0, NULL);
00236 #else
00237 ct = nfct_conntrack_alloc(&orig, &reply, 0,
00238 &proto,
00239 IPS_ASSURED | IPS_SEEN_REPLY, 0,
00240 0, NULL);
00241 #endif
00242 #ifdef HAVE_LIBCONNTRACK_FIXEDTIMEOUT
00243 if (packet_hdr->timeout) {
00244 debug_log_printf(DEBUG_AREA_GW,
00245 DEBUG_LEVEL_VERBOSE_DEBUG,
00246 "Setting timeout to %d after NuAuth request",
00247 ntohl(packet_hdr->timeout));
00248 ct->timeout = ntohl(packet_hdr->timeout);
00249 }
00250 #endif
00251
00252 if (nfct_update_conntrack(cth, ct) != 0) {
00253 log_area_printf(DEBUG_AREA_MAIN,
00254 DEBUG_LEVEL_WARNING,
00255 "Conntrack update was impossible");
00256
00257 }
00258 nfct_conntrack_free(ct);
00259 }
00260 return ntohs(packet_hdr->msg_length);
00261 }
00262 #endif
00263
00274 static int auth_packet_to_decision(char *dgram, int dgram_size)
00275 {
00276 if (dgram_size < 2) {
00277 debug_log_printf(DEBUG_AREA_GW, DEBUG_LEVEL_DEBUG,
00278 "NuAuth sent too small message");
00279 return -1;
00280 }
00281
00282 if (dgram[0] != PROTO_NUFW_VERSION) {
00283 debug_log_printf(DEBUG_AREA_GW, DEBUG_LEVEL_DEBUG,
00284 "Wrong protocol version from authentication server answer.");
00285 return -1;
00286 }
00287
00288 switch (dgram[1]) {
00289 case AUTH_ANSWER:
00290 return auth_process_answer(dgram, dgram_size);
00291 #ifdef HAVE_LIBCONNTRACK
00292 case AUTH_CONN_DESTROY:
00293 return auth_process_conn_destroy(dgram, dgram_size);
00294 case AUTH_CONN_UPDATE:
00295 return auth_process_conn_update(dgram, dgram_size);
00296 #else
00297 case AUTH_CONN_DESTROY:
00298 log_area_printf(DEBUG_AREA_MAIN | DEBUG_AREA_GW,
00299 DEBUG_LEVEL_WARNING,
00300 "Connection destroy message not supported");
00301 break;
00302 case AUTH_CONN_UPDATE:
00303 log_area_printf(DEBUG_AREA_MAIN | DEBUG_AREA_GW,
00304 DEBUG_LEVEL_WARNING,
00305 "Connection update message not supported");
00306 break;
00307 #endif
00308 default:
00309 log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_DEBUG,
00310 "NuAuth message type %d not for me",
00311 dgram[1]);
00312 break;
00313 }
00314 return -1;
00315 }
00316
00321 void *authsrv(void *data)
00322 {
00323 int ret;
00324 int read_size;
00325 char cdgram[512];
00326 char *dgram = cdgram;
00327
00328 log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_VERBOSE_DEBUG,
00329 "[+] Start auth server thread");
00330
00331 while (pthread_mutex_trylock(&tls.auth_server_mutex) == 0) {
00332 pthread_mutex_unlock(&tls.auth_server_mutex);
00333
00334
00335 pthread_mutex_lock(&tls.mutex);
00336 if (tls.session)
00337 ret = nussl_read(tls.session, dgram, sizeof cdgram);
00338 else
00339 ret = 0;
00340 pthread_mutex_unlock(&tls.mutex);
00341 if (ret == NUSSL_SOCK_TIMEOUT)
00342 {
00343 usleep(10000);
00344 continue;
00345 }
00346 if (ret <= 0) {
00347 log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_VERBOSE_DEBUG,
00348 "Error during nussl_read: %s", nussl_get_error(tls.session));
00349 break;
00350 } else {
00351 do {
00352 read_size = auth_packet_to_decision(dgram, ret);
00353 ret -= read_size;
00354 dgram = dgram + read_size;
00355 } while (ret > 0 && (read_size != -1));
00356 }
00357
00358 dgram = cdgram;
00359 }
00360
00361 log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_VERBOSE_DEBUG,
00362 "[+] Leave auth server thread");
00363
00364 pthread_mutex_lock(&tls.mutex);
00365
00366 tls.auth_server_running = 0;
00367 pthread_mutex_unlock(&tls.mutex);
00368 pthread_exit(NULL);
00369 }