int main() { int pass; SshStream s1, s2; ssh_rand_seed((SshUInt32)ssh_time()); ssh_event_loop_initialize(); for (pass = 0; pass < 100; pass++) { ssh_stream_pair_create(&s1, &s2); break_test = ssh_rand() % 2; copy_data_test(s1, s2); ssh_stream_pair_create(&s1, &s2); break_test = ssh_rand() % 2; copy_data_test(s2, s1); } if (testdata) ssh_buffer_free(testdata); if (received_data) ssh_buffer_free(received_data); ssh_event_loop_uninitialize(); ssh_util_uninit(); return 0; }
int main(int argc, char **argv) { srand(ssh_time()); utf8_basic_tests(); ssh_debug("basic tests passed."); utf8_advanced_tests(); ssh_debug("advanced tests passed."); return 0; }
int main() { int pass; srandom(ssh_time()); ssh_event_loop_initialize(); random_state = ssh_random_allocate(); create_server_keys(&hostkey, &serverkey, &hostkey_blob, &hostkey_blob_len); pingpong_success = FALSE; for (pass = 0; pass < 10; pass++) { #ifdef DEBUG ssh_debug("========== iteration %d ==========", pass); #endif disconnect_test(); simple_password_test(NULL); } if (!pingpong_success) ssh_fatal("main: no successful pingpong"); pingpong_success = FALSE; for (pass = 0; pass < 100; pass++) { #ifdef DEBUG ssh_debug("========== iteration dual-%d ==========", pass); #endif disconnect_test(); simple_password_test(dual_policy); } if (!pingpong_success) ssh_fatal("main: no successful pingpong"); ssh_private_key_free(hostkey); ssh_private_key_free(serverkey); ssh_xfree(hostkey_blob); ssh_random_free(random_state); ssh_event_loop_uninitialize(); return 0; }
static void ikev2_fb_i_ipsec_negotiation_cb(SshIkeNotifyMessageType error, SshIkeNegotiation negotiation, void *callback_context) { SshIkev2FbNegotiation neg = NULL; SshIkePMPhaseQm qm_info; /* Take fallback negotiation from `policy_manager_data' to safely deal with negotiation abort. */ qm_info = ikev2_fb_get_qm_info(negotiation); if (qm_info && qm_info->policy_manager_data) neg = (SshIkev2FbNegotiation) qm_info->policy_manager_data; SSH_DEBUG(SSH_D_LOWOK, ("Connect IPSec done callback, status %s (neg %p)", ssh_ike_error_code_to_string(error), neg)); /* If `neg' is NULL then the negotiation has been aborted and freed already and the Quick-Mode thread is gone. */ if (neg == NULL) return; /* If `neg->qm_negotiation' is NULL then this is an error case and the callback was called synchronously from the running thread. */ if (neg->qm_negotiation != NULL) { neg->qm_negotiation = NULL; if (SSH_FSM_THREAD_EXISTS(neg->thread) && !SSH_FSM_IS_THREAD_DONE(neg->thread)) ssh_fsm_continue(neg->thread); } if (error != SSH_IKE_NOTIFY_MESSAGE_CONNECTED) { neg->ike_error = ikev2_fb_v1_notify_message_type_to_v2_error_code(error); neg->v1_error = error; SSH_ASSERT(neg->ike_error != SSH_IKEV2_ERROR_OK); } else { neg->ike_sa->last_input_stamp = ssh_time(); } }
/* * Inserts specified event into log file specified in context. * event parameter specifies the audited event. Each element after event * must start with a SshAuditformat type followed by arguments of the * appropriate type, and the list must end with SSH_AUDIT_ARGUMENT_END. */ void ssh_audit_event(SshAuditContext context, SshAuditEvent event, ...) { size_t bytes; va_list ap; SshBuffer *audit_info, *formated_str; char *audit_time; if (context == NULL) return; if ((event < 0) || (event > SSH_AUDIT_MAX_VALUE)) return; /* Check if given event is allowed */ if (!context->ssh_audit_event_allowed[(int)event]) return; /* Initialize a buffer for output string */ audit_info = ssh_buffer_allocate(); /* Start constructing string which will be inserted into audit log.*/ /* Start with inserting the name of the event.*/ /* then date and time */ audit_time = ssh_time_string(ssh_time()); ssh_buffer_append_cstrs(audit_info, ssh_find_keyword_name(ssh_audit_event_title, (int)event), ": ", audit_time, ": ", NULL); ssh_xfree(audit_time); /* Handle the variable list*/ va_start(ap, event); formated_str = ssh_format_audit_string(ap); va_end(ap); /* Insert given parameters into string*/ ssh_buffer_append(audit_info, ssh_buffer_ptr(formated_str), ssh_buffer_len(formated_str)); ssh_buffer_append(audit_info, (unsigned char *) "\0", 1); /* Output the log message*/ ssh_send_log_message(context, ssh_buffer_ptr(audit_info)); ssh_buffer_free(formated_str); ssh_buffer_free(audit_info); }
/* Allocate new decaying counter, and initialize it to zero. This will start timers to process counter. The decaying counter will calculate running average from the last `interval' seconds */ SshDecayCounter ssh_decay_counter_allocate(SshDecayCounterType type, SshTime interval) { SshDecayCounter counter; if ((counter = ssh_calloc(1, sizeof(*counter))) == NULL) return NULL; if (interval <= 100) { counter->timer = interval / 10; counter->multiplier = ssh_decay_counter_consts[type][0].multiplier; counter->divisior = ssh_decay_counter_consts[type][0].divisior * counter->timer / 1000; } else if (interval <= 300) { counter->timer = interval / 30; counter->multiplier = ssh_decay_counter_consts[type][1].multiplier; counter->divisior = ssh_decay_counter_consts[type][1].divisior * counter->timer / 1000; } else { counter->timer = interval / 60; counter->multiplier = ssh_decay_counter_consts[type][2].multiplier; counter->divisior = ssh_decay_counter_consts[type][2].divisior * counter->timer / 1000; } counter->next_time = ssh_time() + counter->timer; SSH_DEBUG(SSH_D_HIGHSTART, ("Allocated counter, interval = %ld " "(timer = %ld), multiplier = %ld, " "divisior = %ld", (unsigned long) interval, (unsigned long) counter->timer, (unsigned long) counter->multiplier, (unsigned long) counter->divisior)); ssh_register_timeout(&counter->tmout, (long)counter->timer, 0, ssh_decay_counter_timer, counter); return counter; }
/* Decay timer */ void ssh_decay_counter_timer(void *context) { SshDecayCounter counter = context; SshTime now; counter->current *= counter->multiplier; counter->current /= 1000000; counter->last_value = counter->current / counter->divisior; SSH_DEBUG(SSH_D_LOWOK, ("Updating decay counter, value = %ld", (unsigned long) counter->last_value)); counter->next_time += counter->timer; now = ssh_time(); if (counter->next_time < now) ssh_register_timeout(&counter->tmout, 0, 0, ssh_decay_counter_timer, context); else ssh_register_timeout(&counter->tmout, (long)(counter->next_time - now), 0, ssh_decay_counter_timer, context); }
int main() { SshTimeMeasure total_timer; SshTimeMeasure timer_1; SshTimeMeasure timer_2; SshTimeMeasure timer_3; SshTimeMeasure timer_4; SshTimeMeasure timer_5; static struct SshTimeMeasureRec timer_6_rec = SSH_TIME_MEASURE_INITIALIZER; SshTimeMeasure timer_6; int i; double rv = 0.0; int ev = 0; #ifdef HAVE_GETTIMEOFDAY struct timeval tv; #endif /* HAVE_GETTIMEOFDAY */ SshUInt64 seconds; SshUInt32 nanoseconds; total_timer = ssh_time_measure_allocate(); timer_1 = ssh_time_measure_allocate(); timer_2 = ssh_time_measure_allocate(); timer_3 = ssh_time_measure_allocate(); timer_4 = ssh_time_measure_allocate(); timer_5 = ssh_time_measure_allocate(); timer_6 = &timer_6_rec; if (ssh_time_measure_get(timer_5, SSH_TIME_GRANULARITY_NANOSECOND) != 0) { ssh_warning("Weird initial stamp value.\n"); ev++; } if (ssh_time_measure_get(timer_6, SSH_TIME_GRANULARITY_NANOSECOND) != 0) { ssh_warning("Weird initial (static) stamp value.\n"); ev++; } rv = (double)ssh_time_measure_get(total_timer, SSH_TIME_GRANULARITY_SECOND); if ((rv < 0.0) || (rv > 0.0)) { ssh_warning("Weird initial value.\n"); ev++; } ssh_time_measure_granularity(&seconds, &nanoseconds); if ((seconds == 0) && (nanoseconds == 0)) { ssh_warning("Weird granularity.\n"); ev++; } else { printf("granularity is %lu sec %lu nsec\n", (unsigned long)seconds, (unsigned long)nanoseconds); } START(total_timer); START(timer_1); START(timer_3); START(timer_4); START(timer_5); STAMP(total_timer); printf("testing stamps\n"); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); CHECKNANOSTAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); CHECKNANOSTAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); CHECKNANOSTAMP(timer_1); USLEEP(1000000); NANOSTAMP(timer_1); MICROSTAMP(timer_1); MILLISTAMP(timer_1); STAMP(timer_1); CHECKNANOSTAMP(timer_1); USLEEP(2000000); STAMP(total_timer); SET(timer_5, 12345, 12345678); INTERMEDIATE(timer_5); if ((rv < 12345.0) || (rv > 12350.0)) { ssh_warning("Weird intermediate after running set.\n"); ev++; } INTERMEDIATE(timer_1); if (rv < 1.0) { ssh_warning("Weird intermediate.\n"); ev++; } STOP(timer_3); if (rv < 1.0) { ssh_warning("Weird stop value.\n"); ev++; } START(timer_2); RESET(timer_4); USLEEP(3000000); STAMP(total_timer); INTERMEDIATE(timer_2); INTERMEDIATE(timer_5); START(timer_3); if (rv < 1.0) { ssh_warning("Weird restart value.\n"); ev++; } RESET(timer_4); STOP(timer_1); USLEEP(4000000); STAMP(total_timer); STOP(timer_5); #ifdef SSHUINT64_IS_64BITS printf("Setting timer_5 to big value.\n"); ssh_time_measure_set_value(timer_5, ((SshUInt64)0xffffffff) * ((SshUInt64)30), 987654321); INTERMEDIATE(timer_5); if ((rv < 128849018000.0) || (rv > 128849019000.0)) { ssh_warning("Weird intermediate after stopped set.\n"); ev++; } #else SET(timer_5, 1234567890, 987654321); INTERMEDIATE(timer_5); if ((rv < 1234567890.0) || (rv > 1234567900.0)) { ssh_warning("Weird intermediate after stopped set.\n"); ev++; } #endif STOP(timer_4); STOP(timer_3); STOP(timer_2); STOP(timer_1); #define TIMESTAMPS 1000000 ssh_time_measure_reset(timer_1); ssh_time_measure_reset(timer_2); printf("\nGenerating %d timestamps.\n", TIMESTAMPS); START(timer_2); START(timer_1); for (i = 1; i < TIMESTAMPS; i++) { ssh_time_measure_stamp(timer_2, SSH_TIME_GRANULARITY_MICROSECOND); } STOP(timer_1); STOP(timer_2); printf("Time elapsed %.12f seconds (%.12f seconds/timestamp", (double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND), (double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) / (double)TIMESTAMPS); if ((double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) > 0.0) printf(", %d timestamps/second", (int)((double)TIMESTAMPS / (double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND))); printf(")\n"); ssh_time_measure_reset(timer_3); ssh_time_measure_reset(timer_4); printf("\nFor reference generating %d timestamps with time(3).\n", TIMESTAMPS); START(timer_4); START(timer_3); for (i = 1; i < TIMESTAMPS; i++) { ssh_time(); } STOP(timer_3); STOP(timer_4); printf("Time elapsed %.12f seconds (%.12f seconds/timestamp", (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND), (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) / (double)TIMESTAMPS); if ((double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) > 0.0) printf(", %d timestamps/second", (int)((double)TIMESTAMPS / (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND))); printf(")\n"); if (((double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) > 0.0) && ((double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) > 0.0)) printf("Using time(3) is %2.1f%% faster than ssh_..._stamp.\n", (((double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) - (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND)) / (double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND)) * 100.0); #ifdef HAVE_GETTIMEOFDAY ssh_time_measure_reset(timer_3); ssh_time_measure_reset(timer_4); printf("\nFor reference generating %d timestamps with gettimeofday.\n", TIMESTAMPS); START(timer_4); START(timer_3); for (i = 1; i < TIMESTAMPS; i++) { gettimeofday(&tv, NULL); } STOP(timer_3); STOP(timer_4); printf("Time elapsed %.12f seconds (%.12f seconds/timestamp", (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND), (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) / (double)TIMESTAMPS); if ((double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) > 0.0) printf(", %d timestamps/second", (int)((double)TIMESTAMPS / (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND))); printf(")\n"); if (((double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) > 0.0) && ((double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND) > 0.0)) printf("Using gettimeofday(3) is %2.1f%% faster than ssh_..._stamp.\n", (((double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND) - (double)ssh_time_measure_get(timer_3, SSH_TIME_GRANULARITY_SECOND)) / (double)ssh_time_measure_get(timer_1, SSH_TIME_GRANULARITY_SECOND)) * 100.0); #endif /* HAVE_GETTIMEOFDAY */ printf("making start stop test. timers are silently started and stopped.\n"); printf("timer_3 runs while timer_4 is started and stopped in loop.\n"); ssh_time_measure_stop(timer_3); ssh_time_measure_stop(timer_4); ssh_time_measure_reset(timer_3); ssh_time_measure_reset(timer_4); ssh_time_measure_start(timer_3); for (i = 0; i < 1000000; i++) { ssh_time_measure_start(timer_4); ssh_time_measure_stop(timer_4); } ssh_time_measure_stop(timer_3); INTERMEDIATE(timer_4); INTERMEDIATE(timer_3); STOP(total_timer); GET_INT(timer_1); INTERMEDIATE(timer_1); GET_INT(timer_2); INTERMEDIATE(timer_2); GET_INT(timer_3); INTERMEDIATE(timer_3); GET_INT(timer_4); INTERMEDIATE(timer_4); GET_INT(timer_5); INTERMEDIATE(timer_5); GET_INT(total_timer); INTERMEDIATE(total_timer); printf("Testing granularities\n"); GET_NANOSECONDS(total_timer); GET_MICROSECONDS(total_timer); GET_MILLISECONDS(total_timer); GET_SECONDS(total_timer); GET_MINUTES(total_timer); GET_HOURS(total_timer); GET_DAYS(total_timer); GET_WEEKS(total_timer); GET_MONTHS(total_timer); GET_YEARS(total_timer); GET_NANOSECONDS(timer_5); GET_MICROSECONDS(timer_5); GET_MILLISECONDS(timer_5); GET_SECONDS(timer_5); GET_MINUTES(timer_5); GET_HOURS(timer_5); GET_DAYS(timer_5); GET_WEEKS(timer_5); GET_MONTHS(timer_5); GET_MONTHS_2(timer_5); GET_YEARS(timer_5); GET_YEARS_2(timer_5); GET_YEARS_3(timer_5); ssh_time_measure_free(timer_5); ssh_time_measure_free(timer_4); ssh_time_measure_free(timer_3); ssh_time_measure_free(timer_2); ssh_time_measure_free(timer_1); ssh_time_measure_free(total_timer); exit(ev); }
/* * A function implementing system time queries for different platforms. * Be aware that granularity of time measurement may vary on different * hardware and operating systems. Returns FALSE, if system time can't * be retrieved (i.e. system call fails). This function returns time * measured from arbitrary moment in the past. This can be time of * last boot or some other random epoch. */ Boolean ssh_time_measure_system_time(SshTimeVal timeval) { #if defined(WIN32) struct _timeb tv; #elif defined(CHORUS) KnTimeVal tv; #elif defined(HAVE_GETTIMEOFDAY) struct timeval tv; #else /* !WIN32 && !CHORUS && !HAVE_GETTIMEOFDAY */ SshTime tv; #endif /* !WIN32 && !CHORUS && !HAVE_GETTIMEOFDAY */ #if defined(WIN32) _ftime(&tv); if (timeval != NULL) { timeval->seconds = (SshUInt64)tv.time; timeval->nanoseconds = ((SshUInt32)tv.millitm) * 1000000; } return TRUE; #elif defined(CHORUS) if (sysTime(&tv) == K_OK) { if (timeval != NULL) { timeval->seconds = (SshUInt64)tv.tmSec; timeval->nanoseconds = (SshUInt32)tv.tmNSec; } return TRUE; } else { ssh_warning("ssh_time_measure_system_time: sysTime failed."); if (timeval != NULL) { timeval->seconds = 0; timeval->nanoseconds = 0; } return FALSE; } #elif defined(HAVE_GETTIMEOFDAY) if (gettimeofday(&tv, NULL) == 0) { if (timeval != NULL) { timeval->seconds = (SshUInt64)tv.tv_sec; timeval->nanoseconds = ((SshUInt32)tv.tv_usec) * 1000; } return TRUE; } else { ssh_warning("ssh_time_measure_system_time: gettimeofday failed."); if (timeval != NULL) { timeval->seconds = 0; timeval->nanoseconds = 0; } return FALSE; } #else /* !WIN32 && !CHORUS && !HAVE_GETTIMEOFDAY */ tv = ssh_time(); if (timeval != NULL) { timeval->seconds = (SshUInt64)tv; timeval->nanoseconds = (SshUint32)0; } return TRUE; #endif /* !WIN32 && !CHORUS && !HAVE_GETTIMEOFDAY */ }
int main() { int i, j, k, d, y, p; char *a, *b, *first, *last, *rfirst, *rlast; SshTime t, t2; struct SshCalendarTimeRec ct[1], mt[1]; ssh_debug_set_level_string("*=6"); ssh_rand_seed(1234); for (i = 0; i < 1000; i++) { ct->year = 1900 + ssh_rand() % 200; ct->month = ssh_rand() % 12; ct->monthday = 1 + ssh_rand() % 28; ct->hour = ssh_rand() % 24; ct->minute = ssh_rand() % 60; ct->second = ssh_rand() % 60; ct->utc_offset = ((ssh_rand() % 96) - 48) * 900; ct->dst = (ssh_rand() % 3) - 1; if (!ssh_make_time(ct, &t, FALSE)) ssh_fatal("ssh_make_time failed"); ssh_calendar_time(t, mt, FALSE); if (ct->year != mt->year || ct->month != mt->month || ct->monthday != mt->monthday || ct->hour != mt->hour || ct->minute != mt->minute || ct->second != mt->second || ct->weekday != mt->weekday || ct->yearday != mt->yearday) ssh_fatal("Time values are different in struct"); if (!ssh_make_time(mt, &t2, TRUE)) ssh_fatal("ssh_make_time failed"); if (ct->year != mt->year || ct->month != mt->month || ct->monthday != mt->monthday || ct->hour != mt->hour || ct->minute != mt->minute || ct->second != mt->second || ct->weekday != mt->weekday || ct->yearday != mt->yearday) ssh_fatal("Time values are different in struct with local time"); if (mt->dst) t2 -= 3600; if (t2 - t != mt->utc_offset) ssh_fatal("Localtime vs gmtime values does not match!"); } t = ssh_time(); a = ssh_time_string(t); first = ssh_xstrdup(a); rfirst = ssh_readable_time_string(t, TRUE); printf("First value was \"%s\" (%s).\n", first, rfirst); for (i = 0; i < 5; i++) { for (j = 0; j < 100; j++) for (k = 0; k < 1000; k++) { b = ssh_time_string(ssh_time()); if (strcmp(a, b) > 0) { fprintf(stderr, "t-time: ssh_time_string returned value " "\"%s\" after \"%s\", which doesn't sort right.\n", b, a); exit(1); } ssh_xfree(a); a = b; } printf("Intermediate value #%d was \"%s\".\n", i + 1, a); } ssh_xfree(a); t = ssh_time(); last = ssh_time_string(t); rlast = ssh_readable_time_string(t, TRUE); printf("First value was \"%s\" (%s).\n", first, rfirst); printf("Last value was \"%s\" (%s).\n", last, rlast); ssh_xfree(first); ssh_xfree(rfirst); ssh_xfree(last); ssh_xfree(rlast); check_time((SshTime)23200, 1970, 1, 1); /* 01.01.1970 */ check_time((SshTime)68212800, 1972, 2, 29); /* 29.02.1972 */ check_time((SshTime)946641600, 1999, 12, 31); /* 31.12.1999 */ check_time((SshTime)946728000, 2000, 1, 1); /* 01.01.2000 */ check_time((SshTime)951825600, 2000, 2, 29); /* 29.02.2000 */ check_time((SshTime)2147428800, 2038, 1, 18); /* 18.01.2038 */ #define T_TIME_TEST_COUNT 25000 { t = ((SshTime)43200) - (((SshTime)86400) * ((SshTime)T_TIME_TEST_COUNT)); ssh_calendar_time(t, ct, FALSE); a = ssh_readable_time_string(t, TRUE); printf("Testing weekday consistency from: %s\n", a); printf("Be aware that days are in the Gregorian system " "even before the Gregorian era.\n"); ssh_xfree(a); d = ct->weekday; y = ct->year; if ((d < 0) || (d > 6)) { fprintf(stderr, "ssh_calendar_time returns %04d-%02d-%02d " "with wrong weekday %d\n", (int)ct->year, (int)ct->month + 1, (int)ct->monthday, (int)ct->weekday); exit(1); } p = d; for (i = 0; i < (T_TIME_TEST_COUNT * 2); i++) { t += 86400; ssh_calendar_time(t, ct, FALSE); d = (int)ct->weekday; if ((d < 0) || (d > 6) || (d != ((p + 1) % 7))) { fprintf(stderr, "ssh_calendar_time returns %04d-%02d-%02d " "with inconsistent weekday %d\n", (int)ct->year, (int)ct->month + 1, (int)ct->monthday, (int)ct->weekday); exit(1); } #if 1 if ((((ct->year % 100) == 0) && (ct->month == 0) && (ct->monthday == 1)) || (((((ct->year - 20) % 100) == 0) && (ct->month == 5) && (ct->monthday == 24)))) #endif { a = ssh_readable_time_string(t, TRUE); b = ssh_readable_time_string(t, FALSE); printf("Intermediate: %s (universal)\n",b); printf(" %s (local)\n", a); ssh_xfree(a); ssh_xfree(b); } p = d; y = ct->year; } } a = ssh_readable_time_string(t, TRUE); printf("Weekday consistency tested until: %s\n", a); ssh_xfree(a); ssh_util_uninit(); exit(0); }
Boolean ssh_login_permitted(const char *user, SshUser uc) { char passwd[20]; /* Only for account lock check */ strncpy(passwd, uc->correct_encrypted_passwd, sizeof(passwd)); passwd[sizeof(passwd) - 1] = '\0'; #ifdef HAVE_USERSEC_H { char *expiration, current_time[100], normalized[100]; int rlogin_permitted; ssh_time t; struct SshCalendarTimeRec tm[1]; int account_is_locked; if (setuserdb(S_READ) < 0) { if (getuid() == 0) /* It's OK to fail here if we are not root */ { SSH_DEBUG(2, ("setuserdb S_READ failed: %.200s.", strerror(errno))); } return FALSE; } if (getuserattr((char *)user, S_RLOGINCHK, &rlogin_permitted, SEC_BOOL) < 0) { if (getuid() == 0) /* It's OK to fail here if we are not root */ { SSH_DEBUG(2, ("getuserattr S_RLOGINCHK failed: %.200s", strerror(errno))); } enduserdb(); return FALSE; } if (getuserattr((char *)user, S_EXPIRATION, &expiration, SEC_CHAR) < 0) { SSH_DEBUG(2, ("getuserattr S_EXPIRATION failed: %.200s.", strerror(errno))); enduserdb(); return FALSE; } #ifdef S_LOCKED if (getuserattr(user, S_LOCKED, &account_is_locked, SEC_BOOL) < 0) { SSH_DEBUG(2, ("getuserattr S_LOCKED failed: %.200s.", strerror(errno))); enduserdb(); return FALSE; } if (account_is_locked) { SSH_DEBUG(2, ("Account %.100s is locked.", user)); enduserdb(); return FALSE; } #endif /* S_LOCKED */ if (!rlogin_permitted) { SSH_DEBUG(2, ("Remote logins to account %.100s not permitted by " "user profile.", user)); enduserdb(); return FALSE; } if (strcmp(expiration, "0") == 0) { /* The account does not expire - return success immediately. */ enduserdb(); return TRUE; } if (strlen(expiration) != 10) { SSH_DEBUG(2, ("Account %.100s expiration date is in wrong format.", user)); enduserdb(); return FALSE; } t = ssh_time(); ssh_calendar_time(t, tm, TRUE); snprintf(current_time, sizeof(current_time), "%04d%02d%02d%02d%02d", tm->year, tm->month + 1, tm->monthday, tm->hour, tm->minute); if (expiration[8] < '7') /* Assume year < 70 is 20YY. */ strcpy(normalized, "20"); else strcpy(normalized, "19"); strcat(normalized, expiration + 8); strcat(normalized, expiration); normalized[12] = '\0'; if (strcmp(normalized, current_time) < 0) { SSH_DEBUG(2, ("Account %.100s has expired - access denied.", user)); enduserdb(); return FALSE; } enduserdb(); } #endif /* HAVE_USERSEC_H */ #ifdef HAVE_ETC_SHADOW { struct spwd *sp; sp = (struct spwd *)getspnam(user); #if defined(SECURE_RPC) && defined(NIS_PLUS) if (geteuid() == UID_ROOT && ssh_user_uid(uc) != UID_ROOT && (!sp || !sp->sp_pwdp || !strcmp(sp->sp_pwdp,"*NP*"))) { if (seteuid(ssh_user_uid(uc)) >= 0) { sp = getspnam(user); /* retry as user */ seteuid(UID_ROOT); } } #endif /* SECURE_RPC && NIS_PLUS */ if (!sp) { /* * Some systems, e.g.: IRIX, may or may not have /etc/shadow. * Just check if there is one. If such system is also an YP * client, then valid password might already be present in passwd * structure. Just check if it's other than "x". Assume that * YP server is always right if this is the case. * [email protected] */ struct stat sbf; if ((stat(SHADOW, &sbf) == 0) && strcmp(uc->correct_encrypted_passwd, "x") == 0) { SSH_DEBUG(2, ("Can't find %.100s's shadow - access denied.", user)); endspent(); return FALSE; } } else { SshTime today = ssh_time()/24/60/60; /* what a day! */ #ifdef HAVE_STRUCT_SPWD_EXPIRE /* Check for expiration date */ if (sp->sp_expire > 0 && today > sp->sp_expire) { SSH_DEBUG(2, ("Account %.100s has expired - access denied.", user)); endspent(); return FALSE; } #endif #ifdef HAVE_STRUCT_SPWD_INACT /* Check for last login */ if (sp->sp_inact > 0) { char buf[64]; SshTime llt; llt = ssh_user_get_last_login_time(uc, buf, sizeof(buf)); if (llt && (today - llt/24/60/60) > sp->sp_inact) { SSH_DEBUG(2, ("Account %.100s was inactive for more than %d days.", user, sp->sp_inact)); endspent(); return FALSE; } } #endif /* Check if password is valid */ if (sp->sp_lstchg == 0 || (sp->sp_max > 0 && today > sp->sp_lstchg + sp->sp_max)) { SSH_DEBUG(2, ("Account %.100s's password is too old - forced to change.", user)); uc->password_needs_change = TRUE; } strncpy(passwd, sp->sp_pwdp, sizeof(passwd)); passwd[sizeof(passwd) - 1] = '\0'; } endspent(); } #endif /* HAVE_ETC_SHADOW */ /* * Check if account is locked. Check if encrypted password starts * with "*LK*". */ { if (strncmp(passwd,"*LK*", 4) == 0) { SSH_DEBUG(2, ("Account %.100s is locked.", user)); return FALSE; } } #ifdef CHECK_ETC_SHELLS { int invalid = 1; char *shell = pwd->pw_shell, *etc_shell, *getusershell(); if (!shell || !*shell) shell = DEFAULT_SHELL; while (invalid && (etc_shell = getusershell())) invalid = strcmp(etc_shell, shell); endusershell(); if (invalid) { SSH_DEBUG(2, ("Account %.100s doesn't have valid shell", user)); return FALSE; } } #endif /* CHECK_ETC_SHELLS */ return TRUE; }
SshTlsTransStatus ssh_tls_trans_write_client_hello(SshTlsProtocolState s) { SshTlsCipherSuite tab[SSH_TLS_NUM_CIPHERSUITES]; SshTlsCipherSuite *suites_to_send; SshTlsCipherSuiteDetailsStruct details; int number_suites; int contents_len; unsigned char tempbuf[2]; int i; s->kex.flags |= SSH_TLS_KEX_NEW_SESSION; /* Initially. */ if (s->conf.preferred_suites != NULL) { /* If a preference list has been given, check that the preferences are sound w.r.t. the protocol flags given in the configuration. */ SshTlsCipherSuite *tmp; SSH_DEBUG(6, ("Got a preference list.")); number_suites = 0; tmp = s->conf.preferred_suites; while (*tmp != SSH_TLS_NO_CIPHERSUITE) { ssh_tls_get_ciphersuite_details(*tmp, &details); if (details.crippled && (!(s->conf.flags & SSH_TLS_WEAKCIPHERS))) { return SSH_TLS_TRANS_FAILED; } if (details.cipher == SSH_TLS_CIPH_NULL && (!(s->conf.flags & SSH_TLS_NULLCIPHER))) { return SSH_TLS_TRANS_FAILED; } tmp++; number_suites++; } suites_to_send = s->conf.preferred_suites; } else { /* Otherwise construct a list containing all those ciphersuites that are supported by our implementation and that can be used according to the protocol configuration flags. */ number_suites = 0; for (i = SSH_TLS_RSA_WITH_NULL_MD5; i < SSH_TLS_MAX_CIPHERSUITE; i++) { ssh_tls_get_ciphersuite_details(i, &details); SSH_DEBUG(7, ("Check if suite %d can be supported.", i)); if ((details.kex_method == SSH_TLS_UNKNOWN_SUITE) || !(ssh_tls_supported_suite(s->conf.flags, (SshTlsCipherSuite) i))) continue; SSH_DEBUG(7, ("Null? %d Crippled? %d RC2? %d RSA? %d " "Nosign? %d", (details.cipher == SSH_TLS_CIPH_NULL), (details.crippled), (details.cipher == SSH_TLS_CIPH_RC2), (details.kex_method == SSH_TLS_KEX_RSA), (details.signature_method == SSH_TLS_SIGN_NONE))); if ((details.cipher == SSH_TLS_CIPH_NULL && (!(s->conf.flags & SSH_TLS_NULLCIPHER))) || (details.crippled && (!(s->conf.flags & SSH_TLS_WEAKCIPHERS))) || (details.cipher == SSH_TLS_CIPH_RC2) || (details.kex_method != SSH_TLS_KEX_RSA) || (details.signature_method != SSH_TLS_SIGN_NONE)) continue; SSH_DEBUG(7, ("Adding the cipher suite %d.", i)); tab[number_suites++] = i; } suites_to_send = tab; } /* Now we can calculate the length of the packet. */ /* Protocol version 2 bytes, random value 32 bytes, session ID 1 + N bytes, ciphersuites list 2 bytes (length) plus number_suites * 2 bytes, and 2 bytes for the single compression method (no compression) we support. */ contents_len = 2 + 32 + 1 + s->kex.id_len + 2 + number_suites * 2 + 2; /* Initialize the handshake history buffer now. */ SSH_ASSERT(s->kex.handshake_history == NULL); s->kex.handshake_history = ssh_buffer_allocate(); if (s->kex.handshake_history == NULL) return SSH_TLS_TRANS_FAILED; ssh_tls_make_hs_header(s, SSH_TLS_HS_CLIENT_HELLO, contents_len); /* Write the highest protocol version or that of a hopefully-resumed session. */ tempbuf[0] = s->kex.client_version.major; tempbuf[1] = s->kex.client_version.minor; ssh_tls_add_to_kex_packet(s, tempbuf, 2); /* Write unix time. */ SSH_PUT_32BIT(s->kex.client_random, (SshUInt32)ssh_time()); /* Write 28 random bytes. */ for (i = 4; i < 32; i++) { s->kex.client_random[i] = ssh_random_get_byte(); } ssh_tls_add_to_kex_packet(s, s->kex.client_random, 32); /* Write the requested session identifier. */ tempbuf[0] = s->kex.id_len; ssh_tls_add_to_kex_packet(s, &tempbuf[0], 1); if (s->kex.id_len > 0) { ssh_tls_add_to_kex_packet(s, s->kex.session_id, s->kex.id_len); } /* Write the cipher suites. */ SSH_PUT_16BIT(tempbuf, number_suites * 2); ssh_tls_add_to_kex_packet(s, tempbuf, 2); for (i = 0; i < number_suites; i++) { SSH_PUT_16BIT(tempbuf, suites_to_send[i]); ssh_tls_add_to_kex_packet(s, tempbuf, 2); } /* And the compression method. */ tempbuf[0] = 1; tempbuf[1] = 0; /* the null compression */ ssh_tls_add_to_kex_packet(s, tempbuf, 2); s->kex.state = SSH_TLS_KEX_WAIT_S_HELLO; return SSH_TLS_TRANS_OK; }
/* The main test program. */ int main(int argc, char *argv[]) { Boolean verbose = FALSE; SshDlList t_list; SshTimeMeasure ssh_timer; double timer_value; int i, k, evens, odds; /* Initialize the random number generator and timer */ srand((unsigned int)ssh_time()); ssh_timer = ssh_time_measure_allocate(); printf("Running test for SshDlList"); /* Check for verbose output option */ if (argc == 2 && !strcmp("-v", argv[1])) { verbose = TRUE; printf(".\n\n"); } else printf(", use -v for verbose output.\n"); /* Initialize the test data */ test_data = ssh_xmalloc(TEST_NUMBERS * sizeof(TestData)); for (i=0; i < TEST_NUMBERS; i++) test_data[i].number = i; t_list = ssh_dllist_allocate(); /* List addition tests */ for (i=TEST_NUMBERS/2; i < TEST_NUMBERS; i++) if (ssh_dllist_add_item(t_list, (void *)&test_data[i], SSH_DLLIST_END) != SSH_DLLIST_OK) ssh_fatal("t-dllist: list addition failed. Test failed."); if (verbose) print_list(t_list); for (i=TEST_NUMBERS/2-1; i >= 0; i--) if (ssh_dllist_add_item(t_list, (void *)&test_data[i], SSH_DLLIST_BEGIN) != SSH_DLLIST_OK) ssh_fatal("t-dllist: list addition failed. Test failed."); if (verbose) print_list(t_list); /* List searching tests */ if (verbose) printf("Testing list searching... "); ssh_dllist_rewind(t_list); i = 5; ssh_dllist_fw(t_list, i); if (ssh_dllist_current(t_list) != &test_data[i]) ssh_fatal("t-dllist: problems with ssh_dllist_fw. Test failed."); i = 11; ssh_dllist_find(t_list, &test_data[i]); if (ssh_dllist_current(t_list) != &test_data[i]) ssh_fatal("t-dllist: problems with ssh_dllist_find. Test failed."); if (verbose) printf("OK\n"); /* List clear test */ if (verbose) printf("Clearing the list... "); ssh_dllist_clear(t_list); if (verbose) printf("checking is the list empty... "); if (ssh_dllist_is_empty(t_list) != TRUE) ssh_fatal("t-dllist: list NOT empty! Test failed.\n"); else if (verbose) printf("OK\n"); /* ----------------------- performance testing ----------------------- */ /* list addition */ evens = odds = 0; ssh_time_measure_start(ssh_timer); for (k=0; k < ITEMS_TO_ADD_TO_THE_LIST; k++) { i = (int)((rand() / 256) % TEST_NUMBERS); if (i < 0 || i >= TEST_NUMBERS) ssh_fatal("t-dllist: random number calculation produced index out " "of range."); if (i % 2 == 0) evens++; else odds++; ssh_dllist_add_item(t_list, (void *)&test_data[i], SSH_DLLIST_END); } ssh_time_measure_stop(ssh_timer); timer_value = (double)ssh_time_measure_get(ssh_timer, SSH_TIME_GRANULARITY_SECOND); if (verbose) printf("%d item additions took %.2f ms. Added %d evens, %d odds.\n", ITEMS_TO_ADD_TO_THE_LIST, timer_value * 1000, evens, odds); if (evens + odds != ITEMS_TO_ADD_TO_THE_LIST) ssh_fatal("t-dllist: evens + odds does not match. Test failed."); /* list length calculation */ ssh_time_measure_reset(ssh_timer); ssh_time_measure_start(ssh_timer); i = ssh_dllist_length(t_list); ssh_time_measure_stop(ssh_timer); timer_value = (double)ssh_time_measure_get(ssh_timer, SSH_TIME_GRANULARITY_SECOND); if (verbose) printf("Calculating list length took %.2f ms for %d elements.\n", timer_value * 1000, i); if (i != ITEMS_TO_ADD_TO_THE_LIST) ssh_fatal("t-dllist: number of list elements does not match the expected. Test failed."); /* list reverse */ ssh_time_measure_reset(ssh_timer); ssh_time_measure_start(ssh_timer); reverse_list(t_list); ssh_time_measure_stop(ssh_timer); timer_value = (double)ssh_time_measure_get(ssh_timer, SSH_TIME_GRANULARITY_SECOND); if (verbose) printf("List reverse took %.2f ms (reverse is user implemented).\n", timer_value * 1000); /* mapcar test */ ssh_time_measure_reset(ssh_timer); ssh_time_measure_start(ssh_timer); ssh_dllist_mapcar(t_list, remove_evens, NULL); ssh_time_measure_stop(ssh_timer); timer_value = (double)ssh_time_measure_get(ssh_timer, SSH_TIME_GRANULARITY_SECOND); if (verbose) printf("Remove evens with mapcar call, it took %.2f ms, elements left: %d\n", timer_value * 1000, ssh_dllist_length(t_list)); if (ssh_dllist_length(t_list) != odds) ssh_fatal("t-dllist: invalid number of list elements after mapcar. Test failed."); if (verbose) printf("Freeing everything... "); ssh_time_measure_reset(ssh_timer); ssh_time_measure_start(ssh_timer); ssh_dllist_free(t_list); ssh_time_measure_stop(ssh_timer); timer_value = (double)ssh_time_measure_get(ssh_timer, SSH_TIME_GRANULARITY_SECOND); ssh_xfree(test_data); if (verbose) printf("OK, took %.2f ms (list had %d items).\n", timer_value * 1000, odds); return 0; }
/* Process initial contact notification from peer. This function is called before SA installation on the responder */ void ssh_pm_process_initial_contact_notification(SshPm pm, SshPmP1 peer_p1) { SshPmP1 p1, next_p1; SshPmPeer peer, next_peer; SshUInt32 hash, peer_handle; SshTime current_time; SshUInt32 flags; if (ssh_pm_get_status(pm) == SSH_PM_STATUS_DESTROYED) return; SSH_PM_ASSERT_P1(peer_p1); SSH_DEBUG(SSH_D_NICETOKNOW, ("Initial contact notification from %@:%d ID %@", ssh_ipaddr_render, peer_p1->ike_sa->remote_ip, peer_p1->ike_sa->remote_port, ssh_pm_ike_id_render, peer_p1->remote_id)); #ifdef SSHDIST_IPSEC_NAT_TRAVERSAL if (peer_p1->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_THIS_END_BEHIND_NAT || peer_p1->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_OTHER_END_BEHIND_NAT) { if (peer_p1->remote_id->id_type == SSH_IKEV2_ID_TYPE_IPV4_ADDR || peer_p1->remote_id->id_type == SSH_IKEV2_ID_TYPE_IPV6_ADDR) { ssh_log_event(SSH_LOGFACILITY_AUTH, SSH_LOG_WARNING, "NAT-T initial contact notification with IP " "identity %@", ssh_pm_ike_id_render, peer_p1->remote_id); ssh_log_event(SSH_LOGFACILITY_AUTH, SSH_LOG_WARNING, "It is recommended to use non-IP identities with " "NAT-T to avoid ID collisions"); } } #endif /* SSHDIST_IPSEC_NAT_TRAVERSAL */ /* Delete all IKE SA's (except for `peer_p1') that have the same local and remote identities as `peer_p1'. Send delete notification to remote end only if the deleted SA is reasonably new, and we suspect that the other end might end up being out of sync. */ current_time = ssh_time(); /* Compute the hash value from IKE remote ID. */ hash = SSH_PM_IKE_ID_HASH(peer_p1->remote_id); for (p1 = pm->ike_sa_id_hash[hash]; p1; p1 = next_p1) { next_p1 = p1->hash_id_next; /* Do not delete 'p1' */ if (peer_p1 == p1) continue; /* The local identities must agree */ if (!ssh_pm_ikev2_id_compare(peer_p1->local_id, p1->local_id)) continue; /* The remote identities must agree */ if (!ssh_pm_ikev2_id_compare(peer_p1->remote_id, p1->remote_id)) continue; /* Deletion is already ongoing. */ if (SSH_PM_P1_DELETED(p1)) continue; /* Delete immediately all IPsec SA's belonging to this Phase-I. */ /* If the SA has been negotiated recently, then send a delete notification to ensure that both ends are in sync. The SA we are deleting might have been negotiated simultaneously with the SA that included the initial contact notification. If so, then we should make sure that the SA we are deleting does not exist in the other end. */ if ((p1->expire_time - p1->lifetime) > (current_time - SSH_PM_IKE_SA_NEW_LIFETIME)) { peer_handle = ssh_pm_peer_handle_by_p1(pm, p1); /* This IKE SA has no associated IPsec SAs, continue with IKE SA deletion. */ if (peer_handle == SSH_IPSEC_INVALID_INDEX) goto delete_ike_sa; /* Do not use p1 for new negotiations. */ p1->unusable = 1; /* Start deleting all IPsec SAs and the IKE SA. */ if (pm_delete_sas_by_peer_handle(pm, peer_handle) == FALSE) goto delete_ike_sa; } /* Old SA, assume the other end has rebooted, and do not bother to send a delete notification. */ else { delete_ike_sa: /* Now delete the IKE SA and child SAs. */ SSH_DEBUG(SSH_D_MIDOK, ("Deleting the IKE SA %p", p1->ike_sa)); flags = SSH_IKEV2_IKE_DELETE_FLAGS_NO_NOTIFICATION; #ifdef SSHDIST_IKEV1 flags |= SSH_IKEV2_IKE_DELETE_FLAGS_FORCE_DELETE_NOW; #endif /* SSHDIST_IKEV1 */ /* Request child SA deletion. */ p1->delete_child_sas = 1; SSH_ASSERT(p1->initiator_ops[PM_IKE_INITIATOR_OP_DELETE] == NULL); SSH_PM_IKEV2_IKE_SA_DELETE(p1, flags, pm_ike_sa_delete_done_callback); } } /* Delete IPsec SAs, that have no parent IKEv1 SA. */ for (peer = ssh_pm_peer_by_ike_sa_handle(pm, SSH_IPSEC_INVALID_INDEX); peer != NULL; peer = next_peer) { SSH_ASSERT(peer->ike_sa_handle == SSH_IPSEC_INVALID_INDEX); next_peer = ssh_pm_peer_next_by_ike_sa_handle(pm, peer); /* Skip manually keyed SA's. */ if (peer->manual_key) continue; /* Use IP addresses if no identity information is present in the peer */ if (!peer->local_id || !peer->remote_id) { if (SSH_IP_CMP(peer->remote_ip, peer_p1->ike_sa->remote_ip) || peer->remote_port != peer_p1->ike_sa->remote_port) continue; if (SSH_IP_CMP(peer->local_ip, peer_p1->ike_sa->server->ip_address) || peer->local_port != SSH_PM_IKE_SA_LOCAL_PORT(peer_p1->ike_sa)) continue; } else { /* The local identities must agree */ if (!ssh_pm_ikev2_id_compare(peer->local_id, peer_p1->local_id)) continue; /* The remote identities must agree */ if (!ssh_pm_ikev2_id_compare(peer->remote_id, peer_p1->remote_id)) continue; } /* Do not send delete notifications, as there is no IKE SA. */ pm_delete_ipsec_sas_silently_by_peer_handle(pm, peer->peer_handle); } }
int main(int ac, char *av[]) { int i, all, itr, type, args; int gf2n, mod, integer, ecp, ec2n, fec2n, poly2n, bpoly, bits, bits_advance, timing; printf("Arithmetic library test suite\n" "Copyright (C) 1998 SSH Communications Security, Ltd.\n" " All rights reserved.\n" "\n" "Features: \n" " - integer arithmetic\n" " - finite field arithmetic (mod p)\n" "\n"); /* Randomize the random number generator. */ srandom(ssh_time()); /* Don't use this if you want to test the mathlibrary :) */ /*extra_test(); */ /*test_rsa_kphi(); */ all = 0; itr = 1; timing = 0; bits = 512; bits_advance = 128; gf2n = 0; integer = 1; mod = 0; bpoly = 0; ecp = 0; ec2n = 0; fec2n = 0; poly2n = 0; for (i = 1; i < ac; i++) { type = check_arg(av[i], &args); if (args >= ac - i) { printf("error: not enough arguments for '%s'.\n", av[i]); exit(1); } switch (type) { case C_INT: integer = on_off(av[i + 1]); i++; break; case C_MOD: mod = on_off(av[i + 1]); i++; break; case C_BITS: bits = atoi(av[i + 1]); i++; break; case C_BITS_ADV: bits_advance = atoi(av[i + 1]); i++; break; case C_HELP: usage(); break; case C_ALL: all = 1; break; case C_TIMING: timing = 1; break; case C_ITR: itr = atoi(av[i + 1]); i++; break; case C_NONE: printf("error: '%s' not a valid option.\n", av[i]); usage(); break; } } if (itr <= 0) itr = 1; if (bits < 10) bits = 10; for (i = 0; i < itr; i++, bits += bits_advance) { if (bits < 10) bits = 512; if (integer) { test_int(all, bits); if (timing) timing_int(bits); } if (mod) { test_mod(all, bits); if (timing) timing_modular(bits); } } return 0; }
/* Completion callback for ssh_pme_delete_by_peer_handle. This function indicates that the IPsec SA has been destroyed. This function gathers the SPIs of the deleted SAs into the SshPmDeleteByIkeSaCBCtx in context, and continues deleting SAs by peer handle. When all SAs are deleted this sends out the delete notification for the deleted SPIs, and finally deletes the IKE SA. */ static void pm_delete_sas_by_peer_handle_cb(SshPm pm, Boolean done, const SshIpAddr peer_addr, SshUInt16 peer_port, SshUInt8 ipproto, SshUInt32 outbound_spi, SshUInt32 inbound_spi, SshUInt32 peer_handle, void *policy_context, void *context) { SshUInt32 stored_peer_handle = SSH_PM_PTR_TO_UINT32(context); SshPmP1 p1; SshPmStatus pm_status; SshPmPeer peer; /* We have a reference to the IKE peer to make sure it does not disappear. */ peer = ssh_pm_peer_by_handle(pm, stored_peer_handle); SSH_ASSERT(peer != NULL); if (!done) { /* Sanity check ike_sa_handle */ SSH_ASSERT(stored_peer_handle == peer_handle); /* Indicate that the SA has been destroyed. */ ssh_pm_ipsec_sa_event_deleted(pm, outbound_spi, inbound_spi, ipproto); /* Send delete notification for IPSec SA */ SSH_DEBUG(SSH_D_LOWOK, ("Pending delete notification for SPI 0x%08lx", (unsigned long) inbound_spi)); p1 = ssh_pm_p1_from_ike_handle(pm, peer->ike_sa_handle, FALSE); if (p1 == NULL || SSH_PM_P1_DELETED(p1)) SSH_DEBUG(SSH_D_HIGHOK, ("IKE SA is deleted, cannot set pending" " IPsec SA delete notifications.")); else ssh_pm_request_ipsec_delete_notification(pm, p1, ipproto, inbound_spi); /* There are still IPSec SAs for this peer, continue deleting even though we could not set pending delete notifications... */ ssh_pme_delete_by_peer_handle(pm->engine, stored_peer_handle, pm_delete_sas_by_peer_handle_cb, context); } /* All done */ else { SshTime expire_time = ssh_time() + SSH_PM_IKE_EXPIRE_TIMER_SECONDS; /* Check if the IKE SA has been freed */ p1 = ssh_pm_p1_from_ike_handle(pm, peer->ike_sa_handle, FALSE); if (p1 == NULL || SSH_PM_P1_DELETED(p1)) { SSH_DEBUG(SSH_D_HIGHOK, ("IKE SA is already deleted")); /* Free the IKE peer reference. */ ssh_pm_peer_handle_destroy(pm, stored_peer_handle); return; } p1->delete_childless_sa = 1; pm_status = ssh_pm_get_status(pm); if ((pm_status == SSH_PM_STATUS_ACTIVE) || (pm_status == SSH_PM_STATUS_DESTROYED)) { ssh_pm_send_ipsec_delete_notification_requests(pm, p1); } /* In suspended / suspending pm status, just make sure IKE SA won't live too long. */ /* Manually set the expire_time, so that the IKE SA gets deleted in near future in case the sending of IPSec SA delete notification fails. */ if ((p1->expire_time > expire_time) && !SSH_PM_P1_DELETED(p1)) { SSH_DEBUG(SSH_D_MIDOK, ("Marking IKE SA %p for deletion", p1->ike_sa)); p1->expire_time = expire_time; } /* Free the IKE peer reference. */ ssh_pm_peer_handle_destroy(pm, stored_peer_handle); } }
void ikev2_fb_sa_handler(SshIkeNegotiation negotiation, SshIkePMPhaseQm pm_info, int number_of_sas, SshIkeIpsecSelectedSA sas, SshIkeIpsecKeymat keymat, void *sa_callback_context) { SshIkev2FbNegotiation neg; neg = SSH_IKEV2_FB_QM_GET_P1_NEGOTIATION(pm_info); if (neg == NULL) return; neg->ike_sa->last_input_stamp = ssh_time(); SSH_DEBUG(SSH_D_LOWOK, ("SA handler entered, IKE SA %p (neg %p)", pm_info->phase_i->policy_manager_data, neg)); if (number_of_sas != 1) { SSH_DEBUG(SSH_D_FAIL, ("Quick-Mode does not result in one bundle")); goto error; } if (neg->ed->callback) { int i, iproto; SshIkev2PayloadTransform *t; SshIkeIpsecSelectedProtocol p; SshIkeIpsecAttributeEncapsulationModeValues encap; /* Assert that `neg->qm_info' is set correctly. */ SSH_ASSERT(neg->qm_info == pm_info); for (i = 0; i < SSH_IKEV2_TRANSFORM_TYPE_MAX; i++) neg->ed->ipsec_ed->ipsec_sa_transforms[i] = &neg->transforms[i]; /* Fill in the selected transforms into ipsec_ed */ t = neg->ed->ipsec_ed->ipsec_sa_transforms; for (iproto = 0; iproto < sas[0].number_of_protocols; iproto++) { p = &sas[0].protocols[iproto]; if (p->protocol_id == SSH_IKE_PROTOCOL_IPSEC_ESP) { t[SSH_IKEV2_TRANSFORM_TYPE_ENCR]->id = ikev2_fb_v1_esp_id_to_v2_id(p->transform_id.generic); if (p->attributes.key_length) t[SSH_IKEV2_TRANSFORM_TYPE_ENCR]->transform_attribute = (0x800e << 16) | p->attributes.key_length; if (p->attributes.auth_algorithm) t[SSH_IKEV2_TRANSFORM_TYPE_INTEG]->id = ikev2_fb_v1_auth_id_to_v2_id(p->attributes.auth_algorithm); else t[SSH_IKEV2_TRANSFORM_TYPE_INTEG] = NULL; } else if (p->protocol_id == SSH_IKE_PROTOCOL_IPSEC_AH) { t[SSH_IKEV2_TRANSFORM_TYPE_INTEG]->id = ikev2_fb_v1_ah_id_to_v2_id(p->transform_id.generic); t[SSH_IKEV2_TRANSFORM_TYPE_ENCR] = NULL; } else if (p->protocol_id == SSH_IKE_PROTOCOL_IPCOMP) { if (p->spi_size_out == 2) { int j; for (j = 0; j < neg->ipcomp_num; j++) { if (neg->ipcomp_algs[j] == p->transform_id.ipcomp) { neg->ipcomp_num = 1; neg->ipcomp_algs[0] = p->transform_id.ipcomp; neg->ipcomp_cpi_out[0] = SSH_GET_16BIT(p->spi_out); break; } } } } if (p->attributes.group_desc) t[SSH_IKEV2_TRANSFORM_TYPE_D_H]->id = p->attributes.group_desc; else t[SSH_IKEV2_TRANSFORM_TYPE_D_H] = NULL; t[SSH_IKEV2_TRANSFORM_TYPE_ESN]->id = (p->attributes.longseq_size) ? SSH_IKEV2_TRANSFORM_ESN_ESN : SSH_IKEV2_TRANSFORM_ESN_NO_ESN; /* For initiator, notify policymanager about transport mode */ encap = p->attributes.encapsulation_mode; if (encap == IPSEC_VALUES_ENCAPSULATION_MODE_TRANSPORT || encap == IPSEC_VALUES_ENCAPSULATION_MODE_UDP_TRANSPORT || encap == IPSEC_VALUES_ENCAPSULATION_MODE_UDP_DRAFT_TRANSPORT) { (void) ikev2_fb_construct_notify(neg, 0, SSH_IKEV2_NOTIFY_USE_TRANSPORT_MODE, TRUE, 0, NULL, 0, NULL); } } if (neg->ipcomp_num > 0) { for (i = 0; i < neg->ipcomp_num; i++) { unsigned char data[3]; SSH_PUT_16BIT(data, neg->ipcomp_cpi_out[i]); data[2] = neg->ipcomp_algs[i]; (void) ikev2_fb_construct_notify(neg, 0, SSH_IKEV2_NOTIFY_IPCOMP_SUPPORTED, TRUE, 0, NULL, sizeof(data), data); } } } /* Set the outbound SPI to the IPSec exchange data */ if (sas->protocols[0].spi_size_out != 4) goto error; neg->ed->ipsec_ed->spi_outbound = SSH_GET_32BIT(sas->protocols[0].spi_out); SSH_DEBUG(SSH_D_LOWOK, ("Outbound SPI %lx", (unsigned long) neg->ed->ipsec_ed->spi_outbound)); if (!ikev2_fb_fill_keymat(neg->ed, negotiation, sas, keymat)) { SSH_DEBUG(SSH_D_FAIL, ("Cannot generate IKEv2 keying material")); goto error; } SSH_IKEV2_FB_V2_CALL(neg, ipsec_sa_install) (neg->server->sad_handle, neg->ed, ikev2_fb_ipsec_sa_install_done, neg); return; error: /* Even in the case of error, we call the IKEv2 SA installation policy call. The key material is cleared to ensure the installation will fail at the policy manager. */ ssh_free(neg->ed->ipsec_ed->ikev1_keymat); neg->ed->ipsec_ed->ikev1_keymat = NULL; neg->ed->ipsec_ed->ikev1_keymat_len = 0; SSH_IKEV2_FB_V2_CALL(neg, ipsec_sa_install) (neg->server->sad_handle, neg->ed, ikev2_fb_ipsec_sa_install_done, neg); }
int main(int ac, char **av) { char port[100]; int i; TestCase *testcase; int pass; SshTime time_now; time_now = ssh_time(); srandom(time_now); for (pass = 0; pass < PASSES; pass++) { #ifdef DEBUG ssh_debug("pass %d", pass); #endif random_state = ssh_random_allocate(); /* randomize it a bit */ ssh_random_add_noise(random_state, &time_now, sizeof(time_now)); ssh_buffer_init(&testdata); for (i = 0; i < 100000; i++) buffer_put_char(&testdata, ssh_random_get_byte(random_state)); ssh_event_loop_initialize(); for (i = 0; tests[i].name; i++) { testcase = &tests[i]; end_of_script_count = 0; #ifdef DEBUG ssh_debug("Running test %s", testcase->name); #endif snprintf(port, sizeof(port), "%d", (int)(35000 + random() % 1000)); #ifdef DEBUG ssh_debug("Making listener, port %s...", port); #endif listener = ssh_tcp_make_listener("127.0.0.1", port, listener_callback, (void *)testcase); if (!listener) ssh_fatal("making listener failed"); #ifdef DEBUG ssh_debug("Making connect..."); #endif ssh_tcp_connect_with_socks("127.0.0.1", port, NULL, 2, connect_callback, (void *)testcase); #ifdef DEBUG ssh_debug("Event loop running..."); #endif ssh_event_loop_run(); #ifdef DEBUG ssh_debug("Event loop exited..."); #endif if (end_of_script_count != 2) ssh_fatal("end_of_script_count %d, script end not reached.", end_of_script_count); /* Listener was destroyed in callback. */ } ssh_event_loop_uninitialize(); ssh_buffer_uninit(&testdata); ssh_random_free(random_state); } #ifdef DEBUG ssh_debug("Exiting..."); #endif return 0; }
void ikev2_fb_new_connection_phase_qm(SshIkePMPhaseQm pm_info, SshPolicyNewConnectionCB callback_in, void *callback_context_in) { SshIkev2Fb fb = (SshIkev2Fb) pm_info->pm->upper_context; SshIkeServerContext ike_server; SshIkev2FbNegotiation neg; SshIkev2Sa ike_sa; SSH_ASSERT(pm_info->phase_i != NULL); SSH_ASSERT(pm_info->phase_i->policy_manager_data != NULL); ike_sa = (SshIkev2Sa) pm_info->phase_i->policy_manager_data; /* Allocate and init context for this negotiation. */ if ((neg = ikev2_fallback_negotiation_alloc(fb)) == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Out of negotation contexts.")); (*callback_in)(FALSE, SSH_IKE_FLAGS_USE_DEFAULTS, -1, -1, -1, -1, -1, -1, -1, callback_context_in); return; } /* Take a reference to allocated `neg' and set it to `pm_info->policy_manager_data'. */ ikev2_fb_phase_qm_set_pm_data(pm_info, neg); /* Save `neg->qm_info' here for responder negotiations. */ SSH_ASSERT(neg->qm_info == NULL); neg->qm_info = pm_info; /* Lookup the server object used in the negotiation. */ ike_server = ssh_ike_get_server_by_negotiation(pm_info->negotiation); SSH_ASSERT(ike_server != NULL); neg->server = (SshIkev2Server)ike_server; neg->ike_sa = ike_sa; ssh_ikev2_ike_sa_take_ref(neg->ike_sa); neg->ike_sa->last_input_stamp = ssh_time(); if ((neg->ed = ikev2_allocate_exchange_data(neg->ike_sa)) == NULL) goto error; neg->ed->state = SSH_IKEV2_STATE_CREATE_CHILD; if (ikev2_allocate_exchange_data_ipsec(neg->ed) != SSH_IKEV2_ERROR_OK) goto error; SSH_DEBUG(SSH_D_NICETOKNOW, ("Accepting new Quick-Mode negotiation: " "local=%s:%s, remote=%s:%s (neg %p)", pm_info->local_ip, pm_info->local_port, pm_info->remote_ip, pm_info->remote_port, neg)); /* Start the main thread controlling this negotiation */ ssh_fsm_thread_init(fb->fsm, neg->thread, ikev2_fb_qm_negotiation_wait_sa_installation, NULL_FNPTR, ikev2_fb_qm_negotiation_destructor, neg); (*callback_in)(TRUE, SSH_IKE_FLAGS_USE_DEFAULTS, -1, -1, -1, -1, -1, -1, -1, callback_context_in); return; error: SSH_DEBUG(SSH_D_LOWOK, ("New connection failed (neg %p)", neg)); SSH_ASSERT(neg != NULL); /* Release reference to `neg' from `pm_info->policy_manager_data'. */ ikev2_fb_phase_qm_clear_pm_data(pm_info, neg); /* Free negotiation. */ ikev2_fallback_negotiation_free(fb, neg); (*callback_in)(FALSE, SSH_IKE_FLAGS_USE_DEFAULTS, -1, -1, -1, -1, -1, -1, -1, callback_context_in); return; }
/* Import given buffer to the IKE Server given in the argument. Returns the IKE SA negotiation or NULL in case of error. The data that was parsed successfully is consumed from the buffer in any case. If there is extra data after the complete packet then it is left to the buffer. */ SshIkeNegotiation ssh_ike_sa_import(SshBuffer buffer, SshIkeServerContext server) { unsigned char initiator_cookie[SSH_IKE_COOKIE_LENGTH]; unsigned char responder_cookie[SSH_IKE_COOKIE_LENGTH]; unsigned char *auc, *buc, *cuc, *duc; SshUInt32 a32, b32, c32, d32; SshUInt64 a64, b64, c64, d64; SshIkePMPhaseI pm_info; SshIkeNegotiation neg; SshIkeSA sa; size_t len; long l; SshADTHandle h; SshCryptoStatus cret; SshTime t; SshUInt16 local_port; sa = NULL; pm_info = NULL; neg = NULL; auc = NULL; buc = NULL; cuc = NULL; duc = NULL; SSH_DEBUG(5, ("Start")); len = ssh_decode_buffer (buffer, /* Magic number */ SSH_DECODE_UINT32(&a32), /* Version number */ SSH_DECODE_UINT32(&b32), /* Cookies, initiator, responder */ SSH_DECODE_DATA(initiator_cookie, SSH_IKE_COOKIE_LENGTH), SSH_DECODE_DATA(responder_cookie, SSH_IKE_COOKIE_LENGTH), SSH_FORMAT_END); if (len == 0) { SSH_DEBUG(3, ("Could not decode magic, version, cookies")); goto error; } if (a32 != SSH_IKE_EXPORT_MAGIC1) { SSH_DEBUG(3, ("Invalid magic 0x%08x vs 0x%08x", (int) a32, SSH_IKE_EXPORT_MAGIC1)); goto error; } if (b32 != SSH_IKE_EXPORT_VERSION) { SSH_DEBUG(3, ("Invalid version 0x%08x vs 0x%08x", (int) b32, SSH_IKE_EXPORT_VERSION)); goto error; } h = ssh_adt_get_handle_to_equal(server->isakmp_context-> isakmp_cookie_mapping, initiator_cookie); if (h != SSH_ADT_INVALID) { SSH_DEBUG(3, ("Duplicate initiator cookie")); goto error; } sa = ike_sa_allocate(server, initiator_cookie, responder_cookie); if (sa == NULL) { SSH_DEBUG(3, ("ike_sa_allocate_half return error")); goto error; } len = ssh_decode_buffer (buffer, /* Local ip, port. */ SSH_DECODE_UINT32_STR(&auc, NULL), SSH_DECODE_UINT32_STR(&buc, NULL), /* Remote ip, port. */ SSH_DECODE_UINT32_STR(&cuc, NULL), SSH_DECODE_UINT32_STR(&duc, NULL), /* IKE exchange version. */ SSH_DECODE_UINT32(&a32), SSH_DECODE_UINT32(&b32), /* IKE exchange type. */ SSH_DECODE_UINT32(&c32), /* Was this the initiator for the original exchange? */ SSH_DECODE_UINT32(&d32), SSH_FORMAT_END); if (len == 0) { SSH_DEBUG(3, ("Could not decode ip, port, version, exchage type, init")); goto error; } if (!ike_init_isakmp_sa(sa, auc, buc, cuc, duc, a32, b32, c32, d32, FALSE)) { SSH_DEBUG(3, ("Could not init isakmp sa")); goto error; } ssh_free(auc); ssh_free(buc); ssh_free(cuc); ssh_free(duc); auc = NULL; buc = NULL; cuc = NULL; duc = NULL; neg = sa->isakmp_negotiation; pm_info = neg->ike_pm_info; /* Initialize */ sa->phase_1_done = 1; neg->notification_state = SSH_IKE_NOTIFICATION_STATE_ALREADY_SENT; ike_free_negotiation_isakmp(neg); /* Set NAT-T status. */ local_port = ssh_uatoi(sa->isakmp_negotiation->ike_pm_info->local_port); if (local_port != server->normal_local_port) sa->use_natt = 1; /* I think we should count this as SA */ server->statistics->current_ike_sas++; server->statistics->total_ike_sas++; if (neg->ike_pm_info->this_end_is_initiator) { server->statistics->current_ike_sas_initiated++; server->statistics->total_ike_sas_initiated++; } else { server->statistics->current_ike_sas_responded++; server->statistics->total_ike_sas_responded++; } len = ssh_decode_buffer (buffer, /* Byte count and byte limit. */ SSH_DECODE_UINT64(&a64), SSH_DECODE_UINT64(&b64), /* Created time and laste use time */ SSH_DECODE_UINT64(&c64), SSH_DECODE_UINT64(&d64), /* Encryption, hash, prf algorithm names. */ SSH_DECODE_UINT32_STR(&auc, NULL), SSH_DECODE_UINT32_STR(&buc, NULL), SSH_DECODE_UINT32_STR(&cuc, NULL), SSH_FORMAT_END); if (len == 0) { SSH_DEBUG(3, ("Could not decode byte count limit, times, alg names")); goto error; } sa->byte_count = (unsigned long) a64; sa->kbyte_limit = (unsigned long) b64; sa->created_time = (SshTime) c64; sa->last_use_time = (SshTime) d64; l = ssh_find_keyword_number(ssh_ike_encryption_algorithms, ssh_csstr(auc)); if (l == -1) { if (ssh_usstrcmp(auc, "cast128-12-cbc") == 0) sa->encryption_algorithm_name = ssh_custr("cast128-12-cbc"); else { SSH_DEBUG(3, ("Unknown cipher %s", auc)); goto error; } } else { sa->encryption_algorithm_name = ssh_custr(ssh_find_keyword_name(ssh_ike_encryption_algorithms, l)); SSH_ASSERT(sa->encryption_algorithm_name != NULL); } l = ssh_find_keyword_number(ssh_ike_hash_algorithms, ssh_csstr(buc)); if (l == -1) { SSH_DEBUG(3, ("Unknown hash %s", buc)); goto error; } else { sa->hash_algorithm_name = ssh_custr(ssh_find_keyword_name(ssh_ike_hash_algorithms, l)); SSH_ASSERT(sa->hash_algorithm_name != NULL); } l = ssh_find_keyword_number(ssh_ike_hmac_prf_algorithms, ssh_csstr(cuc)); if (l == -1) { SSH_DEBUG(3, ("Unknown prf %s", cuc)); goto error; } else { sa->prf_algorithm_name = ssh_custr(ssh_find_keyword_name(ssh_ike_hmac_prf_algorithms, l)); SSH_ASSERT(sa->prf_algorithm_name != NULL); } ssh_free(auc); ssh_free(buc); ssh_free(cuc); ssh_free(duc); auc = NULL; buc = NULL; cuc = NULL; duc = NULL; len = ssh_decode_buffer (buffer, /* Cipher key. */ SSH_DECODE_UINT32_STR(&sa->cipher_key, &sa->cipher_key_len), /* Cipher IV. */ SSH_DECODE_UINT32_STR(&sa->cipher_iv, &sa->cipher_iv_len), SSH_FORMAT_END); if (len == 0) { SSH_DEBUG(3, ("Could not decode cipher key, iv")); goto error; } len = ssh_decode_buffer (buffer, /* Keying material, Diffie-Hellman. */ SSH_DECODE_UINT32_STR(&sa->skeyid.dh, &sa->skeyid.dh_size), /* Keying material, SKEYID mac. */ SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid, &sa->skeyid.skeyid_size), /* Keying material, SKEYID_d mac. */ SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid_d, &sa->skeyid.skeyid_d_size), /* Keying material, SKEYID_a mac. */ SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid_a, &sa->skeyid.skeyid_a_size), /* Keying material, SKEYID_e mac. */ SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid_e, &sa->skeyid.skeyid_e_size), SSH_FORMAT_END); if (len == 0) { SSH_DEBUG(3, ("Could not decode skeyid")); goto error; } sa->skeyid.initialized = TRUE; cret = ssh_mac_allocate(ssh_csstr(sa->prf_algorithm_name), sa->skeyid.skeyid, sa->skeyid.skeyid_size, &sa->skeyid.skeyid_mac); if (cret != SSH_CRYPTO_OK) { SSH_DEBUG(3, ("ssh_mac_allocate failed: %.200s", ssh_crypto_status_message(cret))); goto error; } cret = ssh_mac_allocate(ssh_csstr(sa->prf_algorithm_name), sa->skeyid.skeyid_a, sa->skeyid.skeyid_a_size, &sa->skeyid.skeyid_a_mac); if (cret != SSH_CRYPTO_OK) { SSH_DEBUG(3, ("ssh_mac_allocate failed: %.200s", ssh_crypto_status_message(cret))); goto error; } cret = ssh_mac_allocate(ssh_csstr(sa->prf_algorithm_name), sa->skeyid.skeyid_e, sa->skeyid.skeyid_e_size, &sa->skeyid.skeyid_e_mac); if (cret != SSH_CRYPTO_OK) { SSH_DEBUG(3, ("ssh_mac_allocate failed: %.200s", ssh_crypto_status_message(cret))); goto error; } len = ssh_decode_buffer (buffer, /* Retry defaults. */ SSH_DECODE_UINT32(&sa->retry_limit), SSH_DECODE_UINT32(&sa->retry_timer), SSH_DECODE_UINT32(&sa->retry_timer_usec), SSH_DECODE_UINT32(&sa->retry_timer_max), SSH_DECODE_UINT32(&sa->retry_timer_max_usec), SSH_DECODE_UINT32(&sa->expire_timer), SSH_DECODE_UINT32(&sa->expire_timer_usec), /* Statistics. */ SSH_DECODE_UINT32(&sa->statistics.packets_in), SSH_DECODE_UINT32(&sa->statistics.packets_out), SSH_DECODE_UINT32(&sa->statistics.octects_in), SSH_DECODE_UINT32(&sa->statistics.octects_out), SSH_DECODE_UINT32(&sa->statistics.created_suites), SSH_DECODE_UINT32(&sa->statistics.deleted_suites), SSH_FORMAT_END); if (len == 0) { SSH_DEBUG(3, ("Could not decode retry, expire timers and stats")); goto error; } len = ssh_decode_buffer (buffer, /* IKE SA negotiation information. */ SSH_DECODE_UINT32(&a32), SSH_DECODE_UINT32(&b32), SSH_DECODE_UINT32(&c32), SSH_FORMAT_END); if (len == 0) { SSH_DEBUG(3, ("Could not decode ike sa info and private group cnt")); goto error; } neg->exchange_type = a32; /* The b32 used to be authe_method_type, but as it was duplicate for the value in pm_info, we ignore it now. */ if (c32 != 0) { ssh_warning("Remote end sent packet including private groups. " "This end does not support transferring of them. " "Private groups ignored"); } len = ssh_decode_buffer (buffer, /* Private groups as UINT32_STRING. */ SSH_DECODE_UINT32_STR(NULL, NULL), SSH_FORMAT_END); if (len == 0) { SSH_DEBUG(3, ("Could not decode private groups info")); goto error; } if (!ssh_ike_sa_import_id(buffer, &pm_info->local_id, &pm_info->local_id_txt)) { SSH_DEBUG(3, ("Could not decode local id")); goto error; } if (!ssh_ike_sa_import_id(buffer, &pm_info->remote_id, &pm_info->remote_id_txt)) { SSH_DEBUG(3, ("Could not decode remote id")); goto error; } len = ssh_decode_buffer (buffer, /* Authentication type. */ SSH_DECODE_UINT32(&a32), SSH_DECODE_UINT32(&b32), /* Start and expire times. */ SSH_DECODE_UINT64(&a64), SSH_DECODE_UINT64(&b64), /* None of the policy manager filled data is copied, this include auth_data, auth_data_len, own_auth_data, own_auth_data_len, public_key, number_of_certificates, number_of_allocated_certificates, certificates, certificate_lens, certificate_encodings, policy_manager_data, pm. */ SSH_DECODE_UINT32(&c32), /* Magic number */ SSH_DECODE_UINT32(&d32), SSH_FORMAT_END); if (len == 0) { SSH_DEBUG(3, ("Could not decode pm info and magic2")); goto error; } pm_info->auth_method_type = a32; pm_info->auth_method = b32; pm_info->sa_start_time = (SshTime) a64; pm_info->sa_expire_time = (SshTime) b64; pm_info->doi = c32; if (d32 != SSH_IKE_EXPORT_MAGIC2) { SSH_DEBUG(3, ("Invalid magic2 0x%08x vs 0x%08x", (int) d32, SSH_IKE_EXPORT_MAGIC2)); goto error; } ssh_cancel_timeouts(SSH_ALL_CALLBACKS, neg); /* Insert expire timer allowing the sa to exists for a while (for bootstrap) */ t = ssh_time(); if (t < pm_info->sa_expire_time) t = pm_info->sa_expire_time - t; else t = 0; t = (t < 30) ? 30 : t; ssh_xregister_timeout((SshUInt32) t, 0, ike_call_ike_remove_isakmp_sa, neg); return neg; error: if (sa != NULL) { if (sa->isakmp_negotiation == NULL) { ike_sa_delete(server->isakmp_context, sa); ssh_free(sa); } else ike_delete_negotiation(sa->isakmp_negotiation); } ssh_free(auc); ssh_free(buc); ssh_free(cuc); ssh_free(duc); return NULL; }