00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "nufw_source.h"
00025 #include "libnuclient.h"
00026 #include <sasl/saslutil.h>
00027 #include <nussl.h>
00028 #include <proto.h>
00029 #include "proc.h"
00030 #include "checks.h"
00031 #include "tcptable.h"
00032 #include "sending.h"
00033
00046 nu_error_t recv_message(nuauth_session_t *session, nuclient_error_t *err)
00047 {
00048 int ret;
00049 char dgram[512];
00050 const size_t message_length =
00051 sizeof(struct nu_header) + sizeof(struct nu_authfield_hello) +
00052 sizeof(struct nu_authreq);
00053 char message[message_length];
00054 struct nu_header *header;
00055 struct nu_authreq *authreq;
00056 struct nu_authfield_hello *hellofield;
00057
00058
00059 header = (struct nu_header *) message;
00060 header->proto = PROTO_VERSION;
00061 header->msg_type = USER_REQUEST;
00062 header->option = 0;
00063 header->length = htons(message_length);
00064
00065 authreq = (struct nu_authreq *) (header + 1);
00066 authreq->packet_seq = session->packet_seq++;
00067 authreq->packet_length =
00068 htons(sizeof(struct nu_authreq) +
00069 sizeof(struct nu_authfield_hello));
00070
00071 hellofield = (struct nu_authfield_hello *) (authreq + 1);
00072 hellofield->type = HELLO_FIELD;
00073 hellofield->option = 0;
00074 hellofield->length = htons(sizeof(struct nu_authfield_hello));
00075
00076 ret = nussl_read(session->nussl, dgram, sizeof dgram);
00077
00078 if (ret == NUSSL_SOCK_TIMEOUT) {
00079 SET_ERROR(err, INTERNAL_ERROR, NO_ERR);
00080 return NU_EXIT_CONTINUE;
00081 }
00082
00083 if (ret <= 0) {
00084 ask_session_end(session);
00085 SET_ERROR(err, INTERNAL_ERROR, SESSION_NOT_CONNECTED_ERR);
00086 return NU_EXIT_ERROR;
00087 }
00088
00089 switch (dgram[0]) {
00090 case SRV_REQUIRED_PACKET:
00091 if (session->debug_mode) {
00092 printf("[+] Client is asked to send new connections.\n");
00093 }
00094 nu_client_real_check(session, err);
00095 break;
00096
00097 case SRV_REQUIRED_HELLO:
00098 hellofield->helloid =
00099 ((struct nu_srv_helloreq *) dgram)->helloid;
00100 if (session->debug_mode) {
00101 printf("[+] Send HELLO\n");
00102 }
00103
00104
00105 ret = nussl_write(session->nussl, message, message_length);
00106 if (ret < 0) {
00107 #if DEBUG_ENABLE
00108 printf("write failed at %s:%d\n",
00109 __FILE__, __LINE__);
00110 #endif
00111 ask_session_end(session);
00112 SET_ERROR(err, INTERNAL_ERROR, SESSION_NOT_CONNECTED_ERR);
00113 return NU_EXIT_ERROR;
00114 }
00115 break;
00116
00117 default:
00118 printf("unknown message\n");
00119 return NU_EXIT_CONTINUE;
00120 }
00121 return NU_EXIT_OK;
00122 }
00123
00124 nu_error_t increase_refresh_delay(nuauth_session_t *session)
00125 {
00126 if (session->sleep_delay.tv_sec * 1000000 +
00127 session->sleep_delay.tv_usec <
00128 session->max_sleep_delay.tv_sec * 1000000 +
00129 session->max_sleep_delay.tv_usec) {
00130 session->sleep_delay.tv_sec = session->sleep_delay.tv_sec * 2 +
00131 (session->sleep_delay.tv_usec * 2) / 1000000;
00132 session->sleep_delay.tv_usec =
00133 session->sleep_delay.tv_usec * 2 % 1000000;
00134
00135
00136 }
00137 return NU_EXIT_OK;
00138 }
00139
00140 nu_error_t reset_refresh_delay(nuauth_session_t *session)
00141 {
00142 session->sleep_delay.tv_sec = session->min_sleep_delay.tv_sec;
00143 session->sleep_delay.tv_usec = session->min_sleep_delay.tv_usec;
00144 return NU_EXIT_OK;
00145 }
00146
00162 int nu_client_check(nuauth_session_t * session, nuclient_error_t * err)
00163 {
00164
00165 if (session->connected == 0) {
00166 SET_ERROR(err, INTERNAL_ERROR, SESSION_NOT_CONNECTED_ERR);
00167 return -1;
00168 }
00169
00170 if (session->server_mode == SRV_TYPE_POLL) {
00171 int checkreturn;
00172
00173 usleep(session->sleep_delay.tv_sec * 1000000 +
00174 session->sleep_delay.tv_usec);
00175 checkreturn = nu_client_real_check(session, err);
00176 if (checkreturn < 0) {
00177
00178 return -1;
00179 } else {
00180 SET_ERROR(err, INTERNAL_ERROR, NO_ERR);
00181 return 1;
00182 }
00183 } else {
00184 struct timeval tv;
00185 fd_set select_set;
00186 int ret;
00187 tv.tv_sec = session->sleep_delay.tv_sec;
00188 tv.tv_usec = session->sleep_delay.tv_usec;
00189
00190 if (session->nussl == NULL) {
00191 SET_ERROR(err, INTERNAL_ERROR, UNKNOWN_ERR);
00192 return -1;
00193 }
00194
00195 FD_ZERO(&select_set);
00196 FD_SET(nussl_session_get_fd(session->nussl), &select_set);
00197 ret = select(nussl_session_get_fd(session->nussl)+1, &select_set, NULL, NULL, &tv);
00198
00199
00200 if (ret == -1) {
00201 ask_session_end(session);
00202 SET_ERROR(err, INTERNAL_ERROR, SESSION_NOT_CONNECTED_ERR);
00203 return -1;
00204 }
00205
00206 if (ret == 0) {
00207 int checkreturn;
00208
00209 checkreturn = nu_client_real_check(session, err);
00210 if (checkreturn < 0) {
00211
00212 return -1;
00213 } else {
00214 SET_ERROR(err, INTERNAL_ERROR, NO_ERR);
00215 if (checkreturn == 0) {
00216 increase_refresh_delay(session);
00217 }
00218 return 1;
00219 }
00220
00221 if ((time(NULL) - session->timestamp_last_sent) >
00222 SENT_TEST_INTERVAL) {
00223 if (!send_hello_pckt(session)) {
00224 SET_ERROR(err, INTERNAL_ERROR,
00225 TIMEOUT_ERR);
00226 return -1;
00227 }
00228 session->timestamp_last_sent = time(NULL);
00229 }
00230 } else {
00231 if (recv_message(session, err) == NU_EXIT_ERROR) {
00232 return -1;
00233 }
00234 }
00235 }
00236 SET_ERROR(err, INTERNAL_ERROR, NO_ERR);
00237 return 1;
00238 }
00239
00250 int nu_client_real_check(nuauth_session_t * session, nuclient_error_t * err)
00251 {
00252 conntable_t *new;
00253 int nb_packets = 0;
00254
00255 if (session->debug_mode) {
00256 printf("[+] Client checking for new connections.\n");
00257 }
00258
00259 if (tcptable_init(&new) == 0) {
00260 SET_ERROR(err, INTERNAL_ERROR, MEMORY_ERR);
00261 return -1;
00262 }
00263 if (tcptable_read(session, new) == 0) {
00264 tcptable_free(new);
00265 SET_ERROR(err, INTERNAL_ERROR, TCPTABLE_ERR);
00266 return -1;
00267 }
00268 #ifdef LINUX
00269
00270 prg_cache_load();
00271 #endif
00272 nb_packets = compare(session, session->ct, new, err);
00273
00274 #ifdef LINUX
00275 prg_cache_clear();
00276 #endif
00277
00278 tcptable_free(session->ct);
00279
00280
00281 if (nb_packets < 0) {
00282 ask_session_end(session);
00283 return nb_packets;
00284 }
00285 session->ct = new;
00286
00287 if (nb_packets > 0) {
00288 reset_refresh_delay(session);
00289 }
00290 return nb_packets;
00291 }
00292
00293