static void setup_utmp(char *ttyname, char *location) { #ifndef OMIT_UTMP #ifdef HAVE_LASTLOG struct lastlog lastlog_entry; FILE *lastlog; #endif struct passwd *pw; FILE *wtmp; pw = getpwuid(getuid()); memset(&utmp_entry, 0, sizeof(utmp_entry)); utmp_entry.ut_type = USER_PROCESS; utmp_entry.ut_pid = getpid(); strncpy(utmp_entry.ut_line, ttyname+5, lenof(utmp_entry.ut_line)); strncpy(utmp_entry.ut_id, ttyname+8, lenof(utmp_entry.ut_id)); strncpy(utmp_entry.ut_user, pw->pw_name, lenof(utmp_entry.ut_user)); strncpy(utmp_entry.ut_host, location, lenof(utmp_entry.ut_host)); time(&utmp_entry.ut_time); #if defined HAVE_PUTUTLINE utmpname(UTMP_FILE); setutent(); pututline(&utmp_entry); endutent(); #endif if ((wtmp = fopen(WTMP_FILE, "a")) != NULL) { fwrite(&utmp_entry, 1, sizeof(utmp_entry), wtmp); fclose(wtmp); } #ifdef HAVE_LASTLOG memset(&lastlog_entry, 0, sizeof(lastlog_entry)); strncpy(lastlog_entry.ll_line, ttyname+5, lenof(lastlog_entry.ll_line)); strncpy(lastlog_entry.ll_host, location, lenof(lastlog_entry.ll_host)); time(&lastlog_entry.ll_time); if ((lastlog = fopen(LASTLOG_FILE, "r+")) != NULL) { fseek(lastlog, sizeof(lastlog_entry) * getuid(), SEEK_SET); fwrite(&lastlog_entry, 1, sizeof(lastlog_entry), lastlog); fclose(lastlog); } #endif pty_stamped_utmp = 1; #endif }
/* * Deal with (and free) an FXP_STATUS packet. Return 1 if * SSH_FX_OK, 0 if SSH_FX_EOF, and -1 for anything else (error). * Also place the status into fxp_errtype. */ static int fxp_got_status(struct sftp_packet *pktin) { static const char *const messages[] = { /* SSH_FX_OK. The only time we will display a _message_ for this * is if we were expecting something other than FXP_STATUS on * success, so this is actually an error message! */ "unexpected OK response", "end of file", "no such file or directory", "permission denied", "failure", "bad message", "no connection", "connection lost", "operation unsupported", }; if (pktin->type != SSH_FXP_STATUS) { fxp_error_message = "expected FXP_STATUS packet"; fxp_errtype = -1; } else { fxp_errtype = get_uint32(pktin); if (get_err(pktin)) { fxp_error_message = "malformed FXP_STATUS packet"; fxp_errtype = -1; } else { if (fxp_errtype < 0 || fxp_errtype >= lenof(messages)) fxp_error_message = "unknown error code"; else fxp_error_message = messages[fxp_errtype]; } } if (fxp_errtype == SSH_FX_OK) return 1; else if (fxp_errtype == SSH_FX_EOF) return 0; else return -1; }
static void setup_utmp(char *ttyname, char *location) { #ifdef HAVE_LASTLOG struct lastlog lastlog_entry; FILE *lastlog; #endif struct passwd *pw; struct timeval tv; pw = getpwuid(getuid()); memset(&utmp_entry, 0, sizeof(utmp_entry)); utmp_entry.ut_type = USER_PROCESS; utmp_entry.ut_pid = getpid(); strncpy(utmp_entry.ut_line, ttyname+5, lenof(utmp_entry.ut_line)); strncpy(utmp_entry.ut_id, ttyname+8, lenof(utmp_entry.ut_id)); strncpy(utmp_entry.ut_user, pw->pw_name, lenof(utmp_entry.ut_user)); strncpy(utmp_entry.ut_host, location, lenof(utmp_entry.ut_host)); /* * Apparently there are some architectures where (struct * utmpx).ut_tv is not essentially struct timeval (e.g. Linux * amd64). Hence the temporary. */ gettimeofday(&tv, NULL); utmp_entry.ut_tv.tv_sec = tv.tv_sec; utmp_entry.ut_tv.tv_usec = tv.tv_usec; setutxent(); pututxline(&utmp_entry); endutxent(); updwtmpx(WTMPX_FILE, &utmp_entry); #ifdef HAVE_LASTLOG memset(&lastlog_entry, 0, sizeof(lastlog_entry)); strncpy(lastlog_entry.ll_line, ttyname+5, lenof(lastlog_entry.ll_line)); strncpy(lastlog_entry.ll_host, location, lenof(lastlog_entry.ll_host)); time(&lastlog_entry.ll_time); if ((lastlog = fopen(LASTLOG_FILE, "r+")) != NULL) { fseek(lastlog, sizeof(lastlog_entry) * getuid(), SEEK_SET); fwrite(&lastlog_entry, 1, sizeof(lastlog_entry), lastlog); fclose(lastlog); } #endif pty_stamped_utmp = 1; }
static int game_fetch_preset(int i, char **name, game_params **params) { char str[80]; game_params *ret; if (i < 0 || i >= lenof(blackbox_presets)) return FALSE; ret = snew(game_params); *ret = blackbox_presets[i]; if (ret->minballs == ret->maxballs) sprintf(str, _("%dx%d, %d balls"), ret->w, ret->h, ret->minballs); else sprintf(str, _("%dx%d, %d-%d balls"), ret->w, ret->h, ret->minballs, ret->maxballs); *name = dupstr(str); *params = ret; return TRUE; }
static void text_output(textfile *tf, const wchar_t *s) { char buf[256]; int ret, len; const wchar_t **sp; if (!s) { sp = NULL; len = 1; } else { sp = &s; len = ustrlen(s); } while (len > 0) { ret = charset_from_unicode(sp, &len, buf, lenof(buf), tf->charset, &tf->state, NULL); if (!sp) len = 0; fwrite(buf, 1, ret, tf->fp); } }
/* {{{ void http_ob_etaghandler(char *, uint, char **, uint *, int) */ void _http_ob_etaghandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC) { /* passthru */ *handled_output_len = output_len; *handled_output = estrndup(output, output_len); /* are we supposed to run? */ if (HTTP_G->etag.started) { /* initialize the etag context */ if (mode & PHP_OUTPUT_HANDLER_START) { HTTP_G->etag.ctx = http_etag_init(); } /* update */ http_etag_update(HTTP_G->etag.ctx, output, output_len); /* finish */ if (mode & PHP_OUTPUT_HANDLER_END) { char *sent_header = NULL; char *etag = http_etag_finish(HTTP_G->etag.ctx); HTTP_G->etag.ctx = NULL; http_send_cache_control(HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)); http_send_etag_ex(etag, strlen(etag), &sent_header); if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) { /* force exit; ob within ob does not work */ HTTP_G->force_exit = 1; http_exit_ex(304, sent_header, etag, 0); } STR_FREE(sent_header); STR_FREE(etag); } } }
static int game_fetch_preset(int i, char **name, game_params **params) { static struct { char *title; game_params params; } presets[] = { { "3x3 rows only", { 3, 3, 2, TRUE, FALSE } }, { "3x3 normal", { 3, 3, 2, FALSE, FALSE } }, { "3x3 orientable", { 3, 3, 2, FALSE, TRUE } }, { "4x4 normal", { 4, 4, 2, FALSE } }, { "4x4 orientable", { 4, 4, 2, FALSE, TRUE } }, { "4x4, rotating 3x3 blocks", { 4, 4, 3, FALSE } }, { "5x5, rotating 3x3 blocks", { 5, 5, 3, FALSE } }, { "6x6, rotating 4x4 blocks", { 6, 6, 4, FALSE } }, }; if (i < 0 || i >= lenof(presets)) return FALSE; *name = dupstr(presets[i].title); *params = dup_params(&presets[i].params); return TRUE; }
static char *validate_params(const game_params *params, int full) { int classes[5]; int i; if (params->solid < 0 || params->solid >= lenof(solids)) return _("Unrecognised solid type"); if (solids[params->solid]->order == 4) { if (params->d1 <= 0 || params->d2 <= 0) return _("Both grid dimensions must be greater than zero"); } else { if (params->d1 <= 0 && params->d2 <= 0) return _("At least one grid dimension must be greater than zero"); } for (i = 0; i < 4; i++) classes[i] = 0; if (params->solid == TETRAHEDRON) classes[4] = 4; else if (params->solid == OCTAHEDRON) classes[4] = 2; else classes[4] = 1; enum_grid_squares(params, count_grid_square_callback, classes); for (i = 0; i < classes[4]; i++) if (classes[i] < solids[params->solid]->nfaces / classes[4]) return _("Not enough grid space to place all blue faces"); if (grid_area(params->d1, params->d2, solids[params->solid]->order) < solids[params->solid]->nfaces + 1) return _("Not enough space to place the solid on an empty square"); return NULL; }
/** * do_buffer_swap: Perform a display buffer swap (call guSync(), swap the * display and work surfaces, wait for the following vertical blank, and * calculate the length of time between this newly displayed frame and the * previous one). Called either from the buffer swap thread or (if the * swap thread fails to start) from the main thread. * * [Parameters] * None * [Return value] * None */ static void do_buffer_swap(void) { guSync(0, 0); sceDisplaySetFrameBuf(surfaces[work_surface], DISPLAY_STRIDE, display_mode, PSP_DISPLAY_SETBUF_NEXTFRAME); displayed_surface = work_surface; work_surface = (work_surface + 1) % lenof(surfaces); sceDisplayWaitVblankStart(); /* Update the frame length variables. If this is the first frame * we've drawn (signaled by last_frame_start == 0), just set a frame * length of 1 (1/60 sec) since we have nothing to compare it against. */ const uint32_t now = sceKernelGetSystemTimeLow(); const uint32_t last_frame_time = now - last_frame_start; const uint32_t time_unit = (1001000+30)/60; if (last_frame_start != 0) { last_frame_length = (last_frame_time + time_unit/2) / time_unit; } else { last_frame_length = 1; } /* Make sure we don't accidentally signal the next frame as the * first frame drawn. */ last_frame_start = (now != 0) ? now : 1; }
int charset_from_localenc(const char *name) { int i; if ( (i = charset_from_mimeenc(name)) != CS_NONE) return i; if ( (i = charset_from_xenc(name)) != CS_NONE) return i; for (i = 0; i < (int)lenof(localencs); i++) { const char *p, *q; p = name; q = localencs[i].name; while (*p || *q) { if (tolower((unsigned char)*p) != tolower((unsigned char)*q)) break; p++; q++; } if (!*p && !*q) return localencs[i].charset; } return CS_NONE; /* not found */ }
void load_open_settings(void *sesskey, Config *cfg) { int i; char prot[10]; cfg->ssh_subsys = 0; /* FIXME: load this properly */ cfg->remote_cmd_ptr = NULL; cfg->remote_cmd_ptr2 = NULL; cfg->ssh_nc_host[0] = '\0'; gpps(sesskey, "HostName", "", cfg->host, sizeof(cfg->host)); gppfile(sesskey, "LogFileName", &cfg->logfilename); gppi(sesskey, "LogType", 0, &cfg->logtype); gppi(sesskey, "LogFileClash", LGXF_ASK, &cfg->logxfovr); gppi(sesskey, "LogFlush", 1, &cfg->logflush); gppi(sesskey, "SSHLogOmitPasswords", 1, &cfg->logomitpass); gppi(sesskey, "SSHLogOmitData", 0, &cfg->logomitdata); gpps(sesskey, "Protocol", "default", prot, 10); cfg->protocol = default_protocol; cfg->port = default_port; { const Backend *b = backend_from_name(prot); if (b) { cfg->protocol = b->protocol; gppi(sesskey, "PortNumber", default_port, &cfg->port); } } /* Address family selection */ gppi(sesskey, "AddressFamily", ADDRTYPE_UNSPEC, &cfg->addressfamily); /* The CloseOnExit numbers are arranged in a different order from * the standard FORCE_ON / FORCE_OFF / AUTO. */ gppi(sesskey, "CloseOnExit", 1, &i); cfg->close_on_exit = (i+1)%3; gppi(sesskey, "WarnOnClose", 1, &cfg->warn_on_close); { /* This is two values for backward compatibility with 0.50/0.51 */ int pingmin, pingsec; gppi(sesskey, "PingInterval", 0, &pingmin); gppi(sesskey, "PingIntervalSecs", 0, &pingsec); cfg->ping_interval = pingmin * 60 + pingsec; } gppi(sesskey, "TCPNoDelay", 1, &cfg->tcp_nodelay); gppi(sesskey, "TCPKeepalives", 0, &cfg->tcp_keepalives); gpps(sesskey, "TerminalType", "xterm", cfg->termtype, sizeof(cfg->termtype)); gpps(sesskey, "TerminalSpeed", "38400,38400", cfg->termspeed, sizeof(cfg->termspeed)); { /* This hardcodes a big set of defaults in any new saved * sessions. Let's hope we don't change our mind. */ int i; char *def = dupstr(""); /* Default: all set to "auto" */ for (i = 0; ttymodes[i]; i++) { char *def2 = dupprintf("%s%s=A,", def, ttymodes[i]); sfree(def); def = def2; } gppmap(sesskey, "TerminalModes", def, cfg->ttymodes, lenof(cfg->ttymodes)); sfree(def); } /* proxy settings */ gpps(sesskey, "ProxyExcludeList", "", cfg->proxy_exclude_list, sizeof(cfg->proxy_exclude_list)); gppi(sesskey, "ProxyDNS", 1, &i); cfg->proxy_dns = (i+1)%3; gppi(sesskey, "ProxyLocalhost", 0, &cfg->even_proxy_localhost); gppi(sesskey, "ProxyMethod", -1, &cfg->proxy_type); if (cfg->proxy_type == -1) { int i; gppi(sesskey, "ProxyType", 0, &i); if (i == 0) cfg->proxy_type = PROXY_NONE; else if (i == 1) cfg->proxy_type = PROXY_HTTP; else if (i == 3) cfg->proxy_type = PROXY_TELNET; else if (i == 4) cfg->proxy_type = PROXY_CMD; else { gppi(sesskey, "ProxySOCKSVersion", 5, &i); if (i == 5) cfg->proxy_type = PROXY_SOCKS5; else cfg->proxy_type = PROXY_SOCKS4; } } gpps(sesskey, "ProxyHost", "proxy", cfg->proxy_host, sizeof(cfg->proxy_host)); gppi(sesskey, "ProxyPort", 80, &cfg->proxy_port); gpps(sesskey, "ProxyUsername", "", cfg->proxy_username, sizeof(cfg->proxy_username)); gpps(sesskey, "ProxyPassword", "", cfg->proxy_password, sizeof(cfg->proxy_password)); gpps(sesskey, "ProxyTelnetCommand", "connect %host %port\\n", cfg->proxy_telnet_command, sizeof(cfg->proxy_telnet_command)); gppmap(sesskey, "Environment", "", cfg->environmt, lenof(cfg->environmt)); gpps(sesskey, "UserName", "", cfg->username, sizeof(cfg->username)); gppi(sesskey, "UserNameFromEnvironment", 0, &cfg->username_from_env); gpps(sesskey, "LocalUserName", "", cfg->localusername, sizeof(cfg->localusername)); gppi(sesskey, "NoPTY", 0, &cfg->nopty); gppi(sesskey, "Compression", 0, &cfg->compression); gppi(sesskey, "TryAgent", 1, &cfg->tryagent); gppi(sesskey, "AgentFwd", 0, &cfg->agentfwd); gppi(sesskey, "ChangeUsername", 0, &cfg->change_username); gppi(sesskey, "GssapiFwd", 0, &cfg->gssapifwd); gprefs(sesskey, "Cipher", "\0", ciphernames, CIPHER_MAX, cfg->ssh_cipherlist); { /* Backward-compatibility: we used to have an option to * disable gex under the "bugs" panel after one report of * a server which offered it then choked, but we never got * a server version string or any other reports. */ char *default_kexes; gppi(sesskey, "BugDHGEx2", 0, &i); i = 2-i; if (i == FORCE_ON) default_kexes = "dh-group14-sha1,dh-group1-sha1,rsa,WARN,dh-gex-sha1"; else default_kexes = "dh-gex-sha1,dh-group14-sha1,dh-group1-sha1,rsa,WARN"; gprefs(sesskey, "KEX", default_kexes, kexnames, KEX_MAX, cfg->ssh_kexlist); } gppi(sesskey, "RekeyTime", 60, &cfg->ssh_rekey_time); gpps(sesskey, "RekeyBytes", "1G", cfg->ssh_rekey_data, sizeof(cfg->ssh_rekey_data)); gppi(sesskey, "SshProt", 2, &cfg->sshprot); gpps(sesskey, "LogHost", "", cfg->loghost, sizeof(cfg->loghost)); gppi(sesskey, "SSH2DES", 0, &cfg->ssh2_des_cbc); gppi(sesskey, "SshNoAuth", 0, &cfg->ssh_no_userauth); gppi(sesskey, "SshBanner", 1, &cfg->ssh_show_banner); gppi(sesskey, "AuthTIS", 0, &cfg->try_tis_auth); gppi(sesskey, "AuthKI", 1, &cfg->try_ki_auth); gppi(sesskey, "AuthGSSAPI", 1, &cfg->try_gssapi_auth); #ifndef NO_GSSAPI gprefs(sesskey, "GSSLibs", "\0", gsslibkeywords, ngsslibs, cfg->ssh_gsslist); gppfile(sesskey, "GSSCustom", &cfg->ssh_gss_custom); #endif gppi(sesskey, "SshNoShell", 0, &cfg->ssh_no_shell); gppfile(sesskey, "PublicKeyFile", &cfg->keyfile); gpps(sesskey, "RemoteCommand", "", cfg->remote_cmd, sizeof(cfg->remote_cmd)); gppi(sesskey, "RFCEnviron", 0, &cfg->rfc_environ); gppi(sesskey, "PassiveTelnet", 0, &cfg->passive_telnet); gppi(sesskey, "BackspaceIsDelete", 1, &cfg->bksp_is_delete); gppi(sesskey, "RXVTHomeEnd", 0, &cfg->rxvt_homeend); gppi(sesskey, "LinuxFunctionKeys", 0, &cfg->funky_type); gppi(sesskey, "NoApplicationKeys", 0, &cfg->no_applic_k); gppi(sesskey, "NoApplicationCursors", 0, &cfg->no_applic_c); gppi(sesskey, "NoMouseReporting", 0, &cfg->no_mouse_rep); gppi(sesskey, "NoRemoteResize", 0, &cfg->no_remote_resize); gppi(sesskey, "NoAltScreen", 0, &cfg->no_alt_screen); gppi(sesskey, "NoRemoteWinTitle", 0, &cfg->no_remote_wintitle); { /* Backward compatibility */ int no_remote_qtitle; gppi(sesskey, "NoRemoteQTitle", 1, &no_remote_qtitle); /* We deliberately interpret the old setting of "no response" as * "empty string". This changes the behaviour, but hopefully for * the better; the user can always recover the old behaviour. */ gppi(sesskey, "RemoteQTitleAction", no_remote_qtitle ? TITLE_EMPTY : TITLE_REAL, &cfg->remote_qtitle_action); } gppi(sesskey, "NoDBackspace", 0, &cfg->no_dbackspace); gppi(sesskey, "NoRemoteCharset", 0, &cfg->no_remote_charset); gppi(sesskey, "ApplicationCursorKeys", 0, &cfg->app_cursor); gppi(sesskey, "ApplicationKeypad", 0, &cfg->app_keypad); gppi(sesskey, "NetHackKeypad", 0, &cfg->nethack_keypad); gppi(sesskey, "AltF4", 1, &cfg->alt_f4); gppi(sesskey, "AltSpace", 0, &cfg->alt_space); gppi(sesskey, "AltOnly", 0, &cfg->alt_only); gppi(sesskey, "AltMetaBit", 0, &cfg->alt_metabit); gppi(sesskey, "CtrlTabSwitch", 0, &cfg->ctrl_tab_switch); gppi(sesskey, "ComposeKey", 0, &cfg->compose_key); gppi(sesskey, "CtrlAltKeys", 1, &cfg->ctrlaltkeys); gppi(sesskey, "RightAltKey", 0, &cfg->rightaltkey); gppi(sesskey, "TelnetKey", 0, &cfg->telnet_keyboard); gppi(sesskey, "TelnetRet", 1, &cfg->telnet_newline); gppi(sesskey, "LocalEcho", AUTO, &cfg->localecho); gppi(sesskey, "LocalEdit", AUTO, &cfg->localedit); gpps(sesskey, "Answerback", "PuTTY", cfg->answerback, sizeof(cfg->answerback)); gppi(sesskey, "AlwaysOnTop", 0, &cfg->alwaysontop); gppi(sesskey, "FullScreenOnAltEnter", 0, &cfg->fullscreenonaltenter); gppi(sesskey, "HideMousePtr", 0, &cfg->hide_mouseptr); gppi(sesskey, "SunkenEdge", 0, &cfg->sunken_edge); gppfile(sesskey, "IconFile", &cfg->iconfile); gppi(sesskey, "WindowBorder", 1, &cfg->window_border); gppi(sesskey, "CurType", 0, &cfg->cursor_type); gppi(sesskey, "BlinkCur", 0, &cfg->blink_cur); { int key, mod, len; char tmp[24]; char buf[256]; int max, t; for (key = 0; key < 256; key++) { sprintf(tmp, "VKey%d", key); gpps(sesskey, tmp, "", buf, sizeof(buf)); max = strlen(buf); if (!max) { continue; } t = 0; for (mod = 0; mod < 8; mod++) { for (len = 0; (t < max) && (buf[t] != ',') && (len < 15); len++, t++) { if (buf[t] == '\\') { sscanf(&buf[++t], "%03o", &cfg->pvkey_codes[key][mod][len]); t += 2; continue; } cfg->pvkey_codes[key][mod][len] = buf[t]; } cfg->pvkey_length[key][mod] = len; cfg->pvkey_codes[key][mod][len] = '\0'; t++; } } } /* pedantic compiler tells me I can't use &cfg->beep as an int * :-) */ gppi(sesskey, "Beep", 1, &cfg->beep); gppi(sesskey, "BeepInd", 0, &cfg->beep_ind); gppfile(sesskey, "BellWaveFile", &cfg->bell_wavefile); gppi(sesskey, "BellOverload", 1, &cfg->bellovl); gppi(sesskey, "BellOverloadN", 5, &cfg->bellovl_n); gppi(sesskey, "BellOverloadT", 2*TICKSPERSEC #ifdef PUTTY_UNIX_H *1000 #endif , &i); cfg->bellovl_t = i #ifdef PUTTY_UNIX_H / 1000 #endif ; gppi(sesskey, "BellOverloadS", 5*TICKSPERSEC #ifdef PUTTY_UNIX_H *1000 #endif , &i); cfg->bellovl_s = i #ifdef PUTTY_UNIX_H / 1000 #endif ; gppi(sesskey, "ScrollbackLines", 200, &cfg->savelines); gppi(sesskey, "DECOriginMode", 0, &cfg->dec_om); gppi(sesskey, "AutoWrapMode", 1, &cfg->wrap_mode); gppi(sesskey, "LFImpliesCR", 0, &cfg->lfhascr); gppi(sesskey, "CRImpliesLF", 0, &cfg->crhaslf); gppi(sesskey, "DisableArabicShaping", 0, &cfg->arabicshaping); gppi(sesskey, "DisableBidi", 0, &cfg->bidi); gppi(sesskey, "WinNameAlways", 1, &cfg->win_name_always); gpps(sesskey, "WinTitle", "", cfg->wintitle, sizeof(cfg->wintitle)); gppi(sesskey, "TermWidth", 80, &cfg->width); gppi(sesskey, "TermHeight", 24, &cfg->height); gppi(sesskey, "TermX", CW_USEDEFAULT, &cfg->x); gppi(sesskey, "TermY", CW_USEDEFAULT, &cfg->y); gppfont(sesskey, "Font", &cfg->font); gppi(sesskey, "FontQuality", FQ_DEFAULT, &cfg->font_quality); gppi(sesskey, "FontVTMode", VT_UNICODE, (int *) &cfg->vtmode); gppi(sesskey, "UseSystemColours", 0, &cfg->system_colour); gppi(sesskey, "TryPalette", 0, &cfg->try_palette); gppi(sesskey, "ANSIColour", 1, &cfg->ansi_colour); gppi(sesskey, "Xterm256Colour", 1, &cfg->xterm_256_colour); gppi(sesskey, "BoldAsColour", 1, &cfg->bold_colour); for (i = 0; i < 24; i++) { static const char *const defaults[] = { "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0", "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85", "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187", "85,85,255", "187,0,187", "255,85,255", "0,187,187", "85,255,255", "187,187,187", "255,255,255", "0,0,0", "255,0,0" }; char buf[20], buf2[30]; int c0, c1, c2; sprintf(buf, "Colour%d", i); gpps(sesskey, buf, defaults[i], buf2, sizeof(buf2)); if (sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) { cfg->colours[i][0] = c0; cfg->colours[i][1] = c1; cfg->colours[i][2] = c2; } } gppi(sesskey, "RawCNP", 0, &cfg->rawcnp); gppi(sesskey, "PasteRTF", 0, &cfg->rtf_paste); gpps(sesskey, "IgnoreChars", "", cfg->ignore_chars, sizeof(cfg->ignore_chars)); gppi(sesskey, "MouseIsXterm", 0, &cfg->mouse_is_xterm); gppi(sesskey, "RectSelect", 0, &cfg->rect_select); gppi(sesskey, "MouseOverride", 1, &cfg->mouse_override); for (i = 0; i < 256; i += 32) { static const char *const defaults[] = { "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1", "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2", "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1", "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2", "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2" }; char buf[20], buf2[256], *p; int j; sprintf(buf, "Wordness%d", i); gpps(sesskey, buf, defaults[i / 32], buf2, sizeof(buf2)); p = buf2; for (j = i; j < i + 32; j++) { char *q = p; while (*p && *p != ',') p++; if (*p == ',') *p++ = '\0'; cfg->wordness[j] = atoi(q); } } /* * The empty default for LineCodePage will be converted later * into a plausible default for the locale. */ { char buf[32]; get_l10n_setting("_LINECODEPAGE_", buf, sizeof (buf)); gpps(sesskey, "LineCodePage", buf, cfg->line_codepage, sizeof(cfg->line_codepage)); } if (!strcmp (cfg->line_codepage, "UTF-8")) { int i; char buf[lenof (cfg->line_codepage)]; gppi (sesskey, "ISO2022", 0, &i); /* for compatibility with old patch */ if (i) { strcpy (buf, "iso2022 "); gpps (sesskey, "ISO2022initstr", "", &buf[8], sizeof buf - 8 * sizeof buf[0]); if (buf[8]) memcpy (cfg->line_codepage, buf, sizeof cfg->line_codepage); } } gppi(sesskey, "CJKAmbigWide", 0, &cfg->cjk_ambig_wide); gppi(sesskey, "UTF8Override", 1, &cfg->utf8_override); gpps(sesskey, "Printer", "", cfg->printer, sizeof(cfg->printer)); gppi (sesskey, "CapsLockCyr", 0, &cfg->xlat_capslockcyr); gppi (sesskey, "Use5Casis", 0, &cfg->use_5casis); gppi(sesskey, "ScrollBar", 1, &cfg->scrollbar); gppi(sesskey, "ScrollBarFullScreen", 0, &cfg->scrollbar_in_fullscreen); gppi(sesskey, "ScrollOnKey", 0, &cfg->scroll_on_key); gppi(sesskey, "ScrollOnDisp", 1, &cfg->scroll_on_disp); gppi(sesskey, "EraseToScrollback", 1, &cfg->erase_to_scrollback); gppi(sesskey, "LockSize", 0, &cfg->resize_action); gppi(sesskey, "BCE", 1, &cfg->bce); gppi(sesskey, "BlinkText", 0, &cfg->blinktext); gppi(sesskey, "X11Forward", 0, &cfg->x11_forward); gpps(sesskey, "X11Display", "", cfg->x11_display, sizeof(cfg->x11_display)); gppi(sesskey, "X11AuthType", X11_MIT, &cfg->x11_auth); gppfile(sesskey, "X11AuthFile", &cfg->xauthfile); gppi(sesskey, "LocalPortAcceptAll", 0, &cfg->lport_acceptall); gppi(sesskey, "RemotePortAcceptAll", 0, &cfg->rport_acceptall); gppmap(sesskey, "PortForwardings", "", cfg->portfwd, lenof(cfg->portfwd)); gppi(sesskey, "BugIgnore1", 0, &i); cfg->sshbug_ignore1 = 2-i; gppi(sesskey, "BugPlainPW1", 0, &i); cfg->sshbug_plainpw1 = 2-i; gppi(sesskey, "BugRSA1", 0, &i); cfg->sshbug_rsa1 = 2-i; gppi(sesskey, "BugIgnore2", 0, &i); cfg->sshbug_ignore2 = 2-i; { int i; gppi(sesskey, "BugHMAC2", 0, &i); cfg->sshbug_hmac2 = 2-i; if (cfg->sshbug_hmac2 == AUTO) { gppi(sesskey, "BuggyMAC", 0, &i); if (i == 1) cfg->sshbug_hmac2 = FORCE_ON; } } gppi(sesskey, "BugDeriveKey2", 0, &i); cfg->sshbug_derivekey2 = 2-i; gppi(sesskey, "BugRSAPad2", 0, &i); cfg->sshbug_rsapad2 = 2-i; gppi(sesskey, "BugPKSessID2", 0, &i); cfg->sshbug_pksessid2 = 2-i; gppi(sesskey, "BugRekey2", 0, &i); cfg->sshbug_rekey2 = 2-i; gppi(sesskey, "BugMaxPkt2", 0, &i); cfg->sshbug_maxpkt2 = 2-i; cfg->ssh_simple = FALSE; gppi(sesskey, "StampUtmp", 1, &cfg->stamp_utmp); gppi(sesskey, "LoginShell", 1, &cfg->login_shell); gppi(sesskey, "ScrollbarOnLeft", 0, &cfg->scrollbar_on_left); gppi(sesskey, "ShadowBold", 0, &cfg->shadowbold); gppfont(sesskey, "BoldFont", &cfg->boldfont); gppfont(sesskey, "WideFont", &cfg->widefont); gppfont(sesskey, "WideBoldFont", &cfg->wideboldfont); gppi(sesskey, "ShadowBoldOffset", 1, &cfg->shadowboldoffset); gpps(sesskey, "SerialLine", "", cfg->serline, sizeof(cfg->serline)); gppi(sesskey, "SerialSpeed", 9600, &cfg->serspeed); gppi(sesskey, "SerialDataBits", 8, &cfg->serdatabits); gppi(sesskey, "SerialStopHalfbits", 2, &cfg->serstopbits); gppi(sesskey, "SerialParity", SER_PAR_NONE, &cfg->serparity); gppi(sesskey, "SerialFlowControl", SER_FLOW_XONXOFF, &cfg->serflow); gpps(sesskey, "WindowClass", "", cfg->winclass, sizeof(cfg->winclass)); /* HACK: PuttyTray / Reconnect */ gppi(sesskey, "WakeupReconnect", 0, &cfg->wakeup_reconnect); gppi(sesskey, "FailureReconnect", 0, &cfg->failure_reconnect); /* Hyperlink */ gppi(sesskey, "HyperlinkEnable", 1, &cfg->url_enable); gppi(sesskey, "HyperlinkUnderline", 1, &cfg->url_underline); gppi(sesskey, "HyperlinkUseCtrlClick", 1, &cfg->url_ctrl_click); /* Background */ gppi(sesskey, "BackgroundWallpaper", 0, &cfg->bg_wallpaper); gppi(sesskey, "BackgroundEffect", 0, &cfg->bg_effect); gppfile(sesskey, "WallpaperFile", &cfg->wp_file); gppi(sesskey, "WallpaperPosition", 0, &cfg->wp_position); gppi(sesskey, "WallpaperAlign", 0, &cfg->wp_align); gppi(sesskey, "WallpaperVerticalAlign", 0, &cfg->wp_valign); gppi(sesskey, "WallpaperMoving", 0, &cfg->wp_moving); /* Transparency */ for (i = 0; i < 4; i++) { static const char *const defaults[] = { "100,100", "100,100", "100,100", "100,100" }; char buf[16], buf2[16]; int c0 = 100; int c1 = 100; sprintf(buf, "Alpha%d", i); gpps(sesskey, buf, defaults[i], buf2, sizeof(buf2)); if (sscanf(buf2, "%d,%d", &c0, &c1)) { if (c0 > 100) { c0 = 100; } if (c1 > 100) { c1 = 100; } cfg->alphas_pc[i][0] = c0; cfg->alphas_pc[i][1] = c1; } } }
/* * Pre-initialisation. This is here to get around the fact that GTK * doesn't like being run in setuid/setgid programs (probably * sensibly). So before we initialise GTK - and therefore before we * even process the command line - we check to see if we're running * set[ug]id. If so, we open our pty master _now_, chown it as * necessary, and drop privileges. We can always close it again * later. If we're potentially going to be doing utmp as well, we * also fork off a utmp helper process and communicate with it by * means of a pipe; the utmp helper will keep privileges in order * to clean up utmp when we exit (i.e. when its end of our pipe * closes). */ void pty_pre_init(void) { Pty pty; #ifndef OMIT_UTMP pid_t pid; int pipefd[2]; #endif pty = single_pty = snew(struct pty_tag); pty->conf = NULL; bufchain_init(&pty->output_data); /* set the child signal handler straight away; it needs to be set * before we ever fork. */ putty_signal(SIGCHLD, sigchld_handler); pty->master_fd = pty->slave_fd = -1; #ifndef OMIT_UTMP pty_stamped_utmp = FALSE; #endif if (geteuid() != getuid() || getegid() != getgid()) { pty_open_master(pty); #ifndef OMIT_UTMP /* * Fork off the utmp helper. */ if (pipe(pipefd) < 0) { perror("pterm: pipe"); exit(1); } cloexec(pipefd[0]); cloexec(pipefd[1]); pid = fork(); if (pid < 0) { perror("pterm: fork"); exit(1); } else if (pid == 0) { char display[128], buffer[128]; int dlen, ret; close(pipefd[1]); /* * Now sit here until we receive a display name from the * other end of the pipe, and then stamp utmp. Unstamp utmp * again, and exit, when the pipe closes. */ dlen = 0; while (1) { ret = read(pipefd[0], buffer, lenof(buffer)); if (ret <= 0) { cleanup_utmp(); _exit(0); } else if (!pty_stamped_utmp) { if (dlen < lenof(display)) memcpy(display+dlen, buffer, min(ret, lenof(display)-dlen)); if (buffer[ret-1] == '\0') { /* * Now we have a display name. NUL-terminate * it, and stamp utmp. */ display[lenof(display)-1] = '\0'; /* * Trap as many fatal signals as we can in the * hope of having the best possible chance to * clean up utmp before termination. We are * unfortunately unprotected against SIGKILL, * but that's life. */ putty_signal(SIGHUP, fatal_sig_handler); putty_signal(SIGINT, fatal_sig_handler); putty_signal(SIGQUIT, fatal_sig_handler); putty_signal(SIGILL, fatal_sig_handler); putty_signal(SIGABRT, fatal_sig_handler); putty_signal(SIGFPE, fatal_sig_handler); putty_signal(SIGPIPE, fatal_sig_handler); putty_signal(SIGALRM, fatal_sig_handler); putty_signal(SIGTERM, fatal_sig_handler); putty_signal(SIGSEGV, fatal_sig_handler); putty_signal(SIGUSR1, fatal_sig_handler); putty_signal(SIGUSR2, fatal_sig_handler); #ifdef SIGBUS putty_signal(SIGBUS, fatal_sig_handler); #endif #ifdef SIGPOLL putty_signal(SIGPOLL, fatal_sig_handler); #endif #ifdef SIGPROF putty_signal(SIGPROF, fatal_sig_handler); #endif #ifdef SIGSYS putty_signal(SIGSYS, fatal_sig_handler); #endif #ifdef SIGTRAP putty_signal(SIGTRAP, fatal_sig_handler); #endif #ifdef SIGVTALRM putty_signal(SIGVTALRM, fatal_sig_handler); #endif #ifdef SIGXCPU putty_signal(SIGXCPU, fatal_sig_handler); #endif #ifdef SIGXFSZ putty_signal(SIGXFSZ, fatal_sig_handler); #endif #ifdef SIGIO putty_signal(SIGIO, fatal_sig_handler); #endif setup_utmp(pty->name, display); } } } } else { close(pipefd[0]); pty_utmp_helper_pid = pid; pty_utmp_helper_pipe = pipefd[1]; } #endif } /* Drop privs. */ { #ifndef HAVE_NO_SETRESUID int gid = getgid(), uid = getuid(); int setresgid(gid_t, gid_t, gid_t); int setresuid(uid_t, uid_t, uid_t); if (setresgid(gid, gid, gid) < 0) { perror("setresgid"); exit(1); } if (setresuid(uid, uid, uid) < 0) { perror("setresuid"); exit(1); } #else if (setgid(getgid()) < 0) { perror("setgid"); exit(1); } if (setuid(getuid()) < 0) { perror("setuid"); exit(1); } #endif } }
Socket new_connection(SockAddr addr, const char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, Conf *conf) { static const struct socket_function_table socket_fn_table = { sk_proxy_plug, sk_proxy_close, sk_proxy_write, sk_proxy_write_oob, sk_proxy_write_eof, sk_proxy_flush, sk_proxy_set_frozen, sk_proxy_socket_error, NULL, /* peer_info */ }; static const struct plug_function_table plug_fn_table = { plug_proxy_log, plug_proxy_closing, plug_proxy_receive, plug_proxy_sent, plug_proxy_accepting}; if (conf_get_int(conf, CONF_proxy_type) != PROXY_NONE && proxy_for_destination(addr, hostname, port, conf)) { Proxy_Socket ret; Proxy_Plug pplug; SockAddr proxy_addr; char *proxy_canonical_name; const char *proxy_type; Socket sret; int type; if ((sret = platform_new_connection(addr, hostname, port, privport, oobinline, nodelay, keepalive, plug, conf)) != NULL) return sret; ret = snew(struct Socket_proxy_tag); ret->fn = &socket_fn_table; ret->conf = conf_copy(conf); ret->plug = plug; ret->remote_addr = addr; /* will need to be freed on close */ ret->remote_port = port; ret->error = NULL; ret->pending_flush = 0; ret->pending_eof = 0; ret->freeze = 0; bufchain_init(&ret->pending_input_data); bufchain_init(&ret->pending_output_data); bufchain_init(&ret->pending_oob_output_data); ret->sub_socket = NULL; ret->state = PROXY_STATE_NEW; ret->negotiate = NULL; type = conf_get_int(conf, CONF_proxy_type); if (type == PROXY_HTTP) { ret->negotiate = proxy_http_negotiate; proxy_type = "HTTP"; } else if (type == PROXY_SOCKS4) { ret->negotiate = proxy_socks4_negotiate; proxy_type = "SOCKS 4"; } else if (type == PROXY_SOCKS5) { ret->negotiate = proxy_socks5_negotiate; proxy_type = "SOCKS 5"; } else if (type == PROXY_TELNET) { ret->negotiate = proxy_telnet_negotiate; proxy_type = "Telnet"; } else { ret->error = "Proxy error: Unknown proxy method"; return (Socket)ret; } { char *logmsg = dupprintf("Will use %s proxy at %s:%d to connect" " to %s:%d", proxy_type, conf_get_str(conf, CONF_proxy_host), conf_get_int(conf, CONF_proxy_port), hostname, port); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* create the proxy plug to map calls from the actual * socket into our proxy socket layer */ pplug = snew(struct Plug_proxy_tag); pplug->fn = &plug_fn_table; pplug->proxy_socket = ret; { char *logmsg = dns_log_msg(conf_get_str(conf, CONF_proxy_host), conf_get_int(conf, CONF_addressfamily), "proxy"); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* look-up proxy */ proxy_addr = sk_namelookup(conf_get_str(conf, CONF_proxy_host), &proxy_canonical_name, conf_get_int(conf, CONF_addressfamily)); if (sk_addr_error(proxy_addr) != NULL) { ret->error = "Proxy error: Unable to resolve proxy host name"; sfree(pplug); sk_addr_free(proxy_addr); return (Socket)ret; } sfree(proxy_canonical_name); { char addrbuf[256], *logmsg; sk_getaddr(proxy_addr, addrbuf, lenof(addrbuf)); logmsg = dupprintf("Connecting to %s proxy at %s port %d", proxy_type, addrbuf, conf_get_int(conf, CONF_proxy_port)); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* create the actual socket we will be using, * connected to our proxy server and port. */ ret->sub_socket = sk_new(proxy_addr, conf_get_int(conf, CONF_proxy_port), privport, oobinline, nodelay, keepalive, (Plug)pplug); if (sk_socket_error(ret->sub_socket) != NULL) return (Socket)ret; /* start the proxy negotiation process... */ sk_set_frozen(ret->sub_socket, 0); ret->negotiate(ret, PROXY_CHANGE_NEW); return (Socket)ret; }
int main(int argc, char **argv) { bool sending; SOCKET *sklist; size_t skcount, sksize; int exitcode; bool errors; bool use_subsystem = false; bool just_test_share_exists = false; enum TriState sanitise_stdout = AUTO, sanitise_stderr = AUTO; unsigned long now, next, then; const struct BackendVtable *vt; dll_hijacking_protection(); sklist = NULL; skcount = sksize = 0; /* * Initialise port and protocol to sensible defaults. (These * will be overridden by more or less anything.) */ default_protocol = PROT_SSH; default_port = 22; flags = 0; cmdline_tooltype |= (TOOLTYPE_HOST_ARG | TOOLTYPE_HOST_ARG_CAN_BE_SESSION | TOOLTYPE_HOST_ARG_PROTOCOL_PREFIX | TOOLTYPE_HOST_ARG_FROM_LAUNCHABLE_LOAD); /* * Process the command line. */ conf = conf_new(); do_defaults(NULL, conf); loaded_session = false; default_protocol = conf_get_int(conf, CONF_protocol); default_port = conf_get_int(conf, CONF_port); errors = false; { /* * Override the default protocol if PLINK_PROTOCOL is set. */ char *p = getenv("PLINK_PROTOCOL"); if (p) { const struct BackendVtable *vt = backend_vt_from_name(p); if (vt) { default_protocol = vt->protocol; default_port = vt->default_port; conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_port, default_port); } } } while (--argc) { char *p = *++argv; int ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL), 1, conf); if (ret == -2) { fprintf(stderr, "plink: option \"%s\" requires an argument\n", p); errors = true; } else if (ret == 2) { --argc, ++argv; } else if (ret == 1) { continue; } else if (!strcmp(p, "-batch")) { console_batch_mode = true; } else if (!strcmp(p, "-s")) { /* Save status to write to conf later. */ use_subsystem = true; } else if (!strcmp(p, "-V") || !strcmp(p, "--version")) { version(); } else if (!strcmp(p, "--help")) { usage(); } else if (!strcmp(p, "-pgpfp")) { pgp_fingerprints(); exit(1); } else if (!strcmp(p, "-shareexists")) { just_test_share_exists = true; } else if (!strcmp(p, "-sanitise-stdout") || !strcmp(p, "-sanitize-stdout")) { sanitise_stdout = FORCE_ON; } else if (!strcmp(p, "-no-sanitise-stdout") || !strcmp(p, "-no-sanitize-stdout")) { sanitise_stdout = FORCE_OFF; } else if (!strcmp(p, "-sanitise-stderr") || !strcmp(p, "-sanitize-stderr")) { sanitise_stderr = FORCE_ON; } else if (!strcmp(p, "-no-sanitise-stderr") || !strcmp(p, "-no-sanitize-stderr")) { sanitise_stderr = FORCE_OFF; } else if (!strcmp(p, "-no-antispoof")) { console_antispoof_prompt = false; } else if (*p != '-') { strbuf *cmdbuf = strbuf_new(); while (argc > 0) { if (cmdbuf->len > 0) put_byte(cmdbuf, ' '); /* add space separator */ put_datapl(cmdbuf, ptrlen_from_asciz(p)); if (--argc > 0) p = *++argv; } conf_set_str(conf, CONF_remote_cmd, cmdbuf->s); conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_bool(conf, CONF_nopty, true); /* command => no tty */ strbuf_free(cmdbuf); break; /* done with cmdline */ } else { fprintf(stderr, "plink: unknown option \"%s\"\n", p); errors = true; } } if (errors) return 1; if (!cmdline_host_ok(conf)) { usage(); } prepare_session(conf); /* * Perform command-line overrides on session configuration. */ cmdline_run_saved(conf); /* * Apply subsystem status. */ if (use_subsystem) conf_set_bool(conf, CONF_ssh_subsys, true); if (!*conf_get_str(conf, CONF_remote_cmd) && !*conf_get_str(conf, CONF_remote_cmd2) && !*conf_get_str(conf, CONF_ssh_nc_host)) flags |= FLAG_INTERACTIVE; /* * Select protocol. This is farmed out into a table in a * separate file to enable an ssh-free variant. */ vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol)); if (vt == NULL) { fprintf(stderr, "Internal fault: Unsupported protocol found\n"); return 1; } sk_init(); if (p_WSAEventSelect == NULL) { fprintf(stderr, "Plink requires WinSock 2\n"); return 1; } /* * Plink doesn't provide any way to add forwardings after the * connection is set up, so if there are none now, we can safely set * the "simple" flag. */ if (conf_get_int(conf, CONF_protocol) == PROT_SSH && !conf_get_bool(conf, CONF_x11_forward) && !conf_get_bool(conf, CONF_agentfwd) && !conf_get_str_nthstrkey(conf, CONF_portfwd, 0)) conf_set_bool(conf, CONF_ssh_simple, true); logctx = log_init(default_logpolicy, conf); if (just_test_share_exists) { if (!vt->test_for_upstream) { fprintf(stderr, "Connection sharing not supported for connection " "type '%s'\n", vt->name); return 1; } if (vt->test_for_upstream(conf_get_str(conf, CONF_host), conf_get_int(conf, CONF_port), conf)) return 0; else return 1; } if (restricted_acl) { lp_eventlog(default_logpolicy, "Running with restricted process ACL"); } /* * Start up the connection. */ netevent = CreateEvent(NULL, false, false, NULL); { const char *error; char *realhost; /* nodelay is only useful if stdin is a character device (console) */ bool nodelay = conf_get_bool(conf, CONF_tcp_nodelay) && (GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR); error = backend_init(vt, plink_seat, &backend, logctx, conf, conf_get_str(conf, CONF_host), conf_get_int(conf, CONF_port), &realhost, nodelay, conf_get_bool(conf, CONF_tcp_keepalives)); if (error) { fprintf(stderr, "Unable to open connection:\n%s", error); return 1; } sfree(realhost); } inhandle = GetStdHandle(STD_INPUT_HANDLE); outhandle = GetStdHandle(STD_OUTPUT_HANDLE); errhandle = GetStdHandle(STD_ERROR_HANDLE); /* * Turn off ECHO and LINE input modes. We don't care if this * call fails, because we know we aren't necessarily running in * a console. */ GetConsoleMode(inhandle, &orig_console_mode); SetConsoleMode(inhandle, ENABLE_PROCESSED_INPUT); /* * Pass the output handles to the handle-handling subsystem. * (The input one we leave until we're through the * authentication process.) */ stdout_handle = handle_output_new(outhandle, stdouterr_sent, NULL, 0); stderr_handle = handle_output_new(errhandle, stdouterr_sent, NULL, 0); handle_sink_init(&stdout_hs, stdout_handle); handle_sink_init(&stderr_hs, stderr_handle); stdout_bs = BinarySink_UPCAST(&stdout_hs); stderr_bs = BinarySink_UPCAST(&stderr_hs); /* * Decide whether to sanitise control sequences out of standard * output and standard error. * * If we weren't given a command-line override, we do this if (a) * the fd in question is pointing at a console, and (b) we aren't * trying to allocate a terminal as part of the session. * * (Rationale: the risk of control sequences is that they cause * confusion when sent to a local console, so if there isn't one, * no problem. Also, if we allocate a remote terminal, then we * sent a terminal type, i.e. we told it what kind of escape * sequences we _like_, i.e. we were expecting to receive some.) */ if (sanitise_stdout == FORCE_ON || (sanitise_stdout == AUTO && is_console_handle(outhandle) && conf_get_bool(conf, CONF_nopty))) { stdout_scc = stripctrl_new(stdout_bs, true, L'\0'); stdout_bs = BinarySink_UPCAST(stdout_scc); } if (sanitise_stderr == FORCE_ON || (sanitise_stderr == AUTO && is_console_handle(errhandle) && conf_get_bool(conf, CONF_nopty))) { stderr_scc = stripctrl_new(stderr_bs, true, L'\0'); stderr_bs = BinarySink_UPCAST(stderr_scc); } main_thread_id = GetCurrentThreadId(); sending = false; now = GETTICKCOUNT(); while (1) { int nhandles; HANDLE *handles; int n; DWORD ticks; if (!sending && backend_sendok(backend)) { stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL, 0); sending = true; } if (toplevel_callback_pending()) { ticks = 0; next = now; } else if (run_timers(now, &next)) { then = now; now = GETTICKCOUNT(); if (now - then > next - then) ticks = 0; else ticks = next - now; } else { ticks = INFINITE; /* no need to initialise next here because we can never * get WAIT_TIMEOUT */ } handles = handle_get_events(&nhandles); handles = sresize(handles, nhandles+1, HANDLE); handles[nhandles] = netevent; n = MsgWaitForMultipleObjects(nhandles+1, handles, false, ticks, QS_POSTMESSAGE); if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) { handle_got_event(handles[n - WAIT_OBJECT_0]); } else if (n == WAIT_OBJECT_0 + nhandles) { WSANETWORKEVENTS things; SOCKET socket; int i, socketstate; /* * We must not call select_result() for any socket * until we have finished enumerating within the tree. * This is because select_result() may close the socket * and modify the tree. */ /* Count the active sockets. */ i = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) i++; /* Expand the buffer if necessary. */ sgrowarray(sklist, sksize, i); /* Retrieve the sockets into sklist. */ skcount = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) { sklist[skcount++] = socket; } /* Now we're done enumerating; go through the list. */ for (i = 0; i < skcount; i++) { WPARAM wp; socket = sklist[i]; wp = (WPARAM) socket; if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) { static const struct { int bit, mask; } eventtypes[] = { {FD_CONNECT_BIT, FD_CONNECT}, {FD_READ_BIT, FD_READ}, {FD_CLOSE_BIT, FD_CLOSE}, {FD_OOB_BIT, FD_OOB}, {FD_WRITE_BIT, FD_WRITE}, {FD_ACCEPT_BIT, FD_ACCEPT}, }; int e; noise_ultralight(NOISE_SOURCE_IOID, socket); for (e = 0; e < lenof(eventtypes); e++) if (things.lNetworkEvents & eventtypes[e].mask) { LPARAM lp; int err = things.iErrorCode[eventtypes[e].bit]; lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err); select_result(wp, lp); } } } } else if (n == WAIT_OBJECT_0 + nhandles + 1) { MSG msg; while (PeekMessage(&msg, INVALID_HANDLE_VALUE, WM_AGENT_CALLBACK, WM_AGENT_CALLBACK, PM_REMOVE)) { struct agent_callback *c = (struct agent_callback *)msg.lParam; c->callback(c->callback_ctx, c->data, c->len); sfree(c); } } run_toplevel_callbacks(); if (n == WAIT_TIMEOUT) { now = next; } else { now = GETTICKCOUNT(); } sfree(handles); if (sending) handle_unthrottle(stdin_handle, backend_sendbuffer(backend)); if (!backend_connected(backend) && handle_backlog(stdout_handle) + handle_backlog(stderr_handle) == 0) break; /* we closed the connection */ } exitcode = backend_exitcode(backend); if (exitcode < 0) { fprintf(stderr, "Remote process exit code unavailable\n"); exitcode = 1; /* this is an error condition */ } cleanup_exit(exitcode); return 0; /* placate compiler warning */ }
static void auth_begin(void) { const char *param = FCGX_GetParam("HTTP_AUTHORIZATION", envp); uint8_t buf[AUTHTOK_BIN_LEN], key[AUTH_KEY_LEN]; unsigned int blen = sizeof(buf); time_t reqdate, now; if(!param || strlen(param) != lenof("SKY ") + AUTHTOK_ASCII_LEN || strncmp(param, "SKY ", 4)) return; if(sxi_b64_dec_core(param+4, buf, &blen) || blen != sizeof(buf)) return; memcpy(user, buf, sizeof(user)); memcpy(rhmac, buf+20, sizeof(rhmac)); if(sx_hashfs_get_user_info(hashfs, user, &uid, key, &role) != OK) /* no such user */ { WARN("No such user: %s", param+4); return; } DEBUG("Request from uid %lld", (long long)uid); if(!sxi_hmac_init_ex(&hmac_ctx, key, sizeof(key), EVP_sha1(), NULL)) { WARN("hmac_init failed"); quit_errmsg(500, "Failed to initialize crypto engine"); } param = FCGX_GetParam("REQUEST_METHOD", envp); if(!param) return; if(!hmac_update_str(&hmac_ctx, param)) quit_errmsg(500, "Failed to initialize crypto engine"); param = FCGX_GetParam("REQUEST_URI", envp); if(!param) return; if(!hmac_update_str(&hmac_ctx, param+1)) quit_errmsg(500, "Failed to initialize crypto engine"); param = FCGX_GetParam("HTTP_DATE", envp); if(!param) quit_errmsg(400, "Missing Date: header"); if(httpdate_to_time_t(param, &reqdate)) quit_errmsg(400, "Date header in wrong format"); now = time(NULL); if(reqdate < now - MAX_CLOCK_DRIFT * 60 || reqdate > now + MAX_CLOCK_DRIFT * 60) quit_errmsg(400, "Client clock drifted more than "STRIFY(MAX_CLOCK_DRIFT)" minutes"); if(!hmac_update_str(&hmac_ctx, param)) quit_errmsg(500, "Failed to initialize crypto engine"); if(!content_len()) { uint8_t chmac[20]; unsigned int chmac_len = 20; if(!hmac_update_str(&hmac_ctx, "da39a3ee5e6b4b0d3255bfef95601890afd80709")) quit_errmsg(500, "Failed to initialize crypto engine"); if(!sxi_hmac_final(&hmac_ctx, chmac, &chmac_len)) quit_errmsg(500, "Failed to initialize crypto engine"); if(!hmac_compare(chmac, rhmac, sizeof(rhmac))) { authed = AUTH_OK; } else { /* WARN("auth mismatch"); */ } return; } else authed = AUTH_BODYCHECK; }
static int asn1_get_rsa_pubkey(fmap_t *map, const void **asn1data, unsigned int *size, cli_crt *x509) { struct cli_asn1 obj; unsigned int avail, avail2; if(asn1_expect_objtype(map, *asn1data, size, &obj, 0x30)) /* subjectPublicKeyInfo */ return 1; *asn1data = obj.next; avail = obj.size; if(asn1_expect_algo(map, &obj.content, &avail, lenof(OID_rsaEncryption), OID_rsaEncryption)) /* rsaEncryption */ return 1; if(asn1_expect_objtype(map, obj.content, &avail, &obj, 0x03)) /* BIT STRING - subjectPublicKey */ return 1; if(avail) { cli_dbgmsg("asn1_get_rsa_pubkey: found unexpected extra data in subjectPublicKeyInfo\n"); return 1; } /* if(obj.size != 141 && obj.size != 271) /\* encoded len of 1024 and 2048 bit public keys *\/ */ /* return 1; */ if(!fmap_need_ptr_once(map, obj.content, 1)) { cli_dbgmsg("asn1_get_rsa_pubkey: cannot read public key content\n"); return 1; } if(((uint8_t *)obj.content)[0] != 0) { /* no byte fragments */ cli_dbgmsg("asn1_get_rsa_pubkey: unexpected byte frags in public key\n"); return 1; } avail = obj.size - 1; obj.content = ((uint8_t *)obj.content) + 1; if(asn1_expect_objtype(map, obj.content, &avail, &obj, 0x30)) /* SEQUENCE */ return 1; if(avail) { cli_dbgmsg("asn1_get_rsa_pubkey: found unexpected extra data in public key content\n"); return 1; } avail = obj.size; if(asn1_expect_objtype(map, obj.content, &avail, &obj, 0x02)) /* INTEGER - mod */ return 1; if(obj.size < 1024/8 || obj.size > 4096/8+1) { cli_dbgmsg("asn1_get_rsa_pubkey: modulus has got an unsupported length (%u)\n", obj.size * 8); return 1; } avail2 = obj.size; if(!fmap_need_ptr_once(map, obj.content, avail2)) { cli_dbgmsg("asn1_get_rsa_pubkey: cannot read n\n"); return 1; } if(mp_read_unsigned_bin(&x509->n, obj.content, avail2)) { cli_dbgmsg("asn1_get_rsa_pubkey: cannot convert n to big number\n"); return 1; } if(asn1_expect_objtype(map, obj.next, &avail, &obj, 0x02)) /* INTEGER - exp */ return 1; if(avail) { cli_dbgmsg("asn1_get_rsa_pubkey: found unexpected extra data after exp\n"); return 1; } if(obj.size < 1 || obj.size > avail2) { cli_dbgmsg("asn1_get_rsa_pubkey: exponent has got an unsupported length (%u)\n", obj.size * 8); return 1; } if(!fmap_need_ptr_once(map, obj.content, obj.size)) { cli_dbgmsg("asn1_get_rsa_pubkey: cannot read e\n"); return 1; } if(mp_read_unsigned_bin(&x509->e, obj.content, obj.size)) { cli_dbgmsg("asn1_get_rsa_pubkey: cannot convert e to big number\n"); return 1; } return 0; }
static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmgr *cmgr, int embedded, const void **hashes, unsigned int *hashes_size, struct cl_engine *engine) { struct cli_asn1 asn1, deep, deeper; uint8_t sha1[SHA1_HASH_SIZE], issuer[SHA1_HASH_SIZE], md[SHA1_HASH_SIZE], serial[SHA1_HASH_SIZE]; const uint8_t *message, *attrs; unsigned int dsize, message_size, attrs_size; cli_crt_hashtype hashtype; cli_crt *x509; void *ctx; int result; int isBlacklisted = 0; cli_dbgmsg("in asn1_parse_mscat\n"); do { if(!(message = fmap_need_off_once(map, offset, 1))) { cli_dbgmsg("asn1_parse_mscat: failed to read pkcs#7 entry\n"); break; } if(asn1_expect_objtype(map, message, &size, &asn1, 0x30)) /* SEQUENCE */ break; /* if(size) { */ /* cli_dbgmsg("asn1_parse_mscat: found extra data after pkcs#7 %u\n", size); */ /* break; */ /* } */ size = asn1.size; if(asn1_expect_obj(map, &asn1.content, &size, 0x06, lenof(OID_signedData), OID_signedData)) /* OBJECT 1.2.840.113549.1.7.2 - contentType = signedData */ break; if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0xa0)) /* [0] - content */ break; if(size) { cli_dbgmsg("asn1_parse_mscat: found extra data in pkcs#7\n"); break; } size = asn1.size; if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) /* SEQUENCE */ break; if(size) { cli_dbgmsg("asn1_parse_mscat: found extra data in signedData\n"); break; } size = asn1.size; if(asn1_expect_obj(map, &asn1.content, &size, 0x02, 1, "\x01")) /* INTEGER - VERSION 1 */ break; if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x31)) /* SET OF DigestAlgorithmIdentifier */ break; if(asn1_expect_algo(map, &asn1.content, &asn1.size, lenof(OID_sha1), OID_sha1)) /* DigestAlgorithmIdentifier[0] == sha1 */ break; if(asn1.size) { cli_dbgmsg("asn1_parse_mscat: only one digestAlgorithmIdentifier is allowed\n"); break; } if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x30)) /* SEQUENCE - contentInfo */ break; /* Here there is either a PKCS #7 ContentType Object Identifier for Certificate Trust List (szOID_CTL) * or a single SPC_INDIRECT_DATA_OBJID */ if( (!embedded && asn1_expect_obj(map, &asn1.content, &asn1.size, 0x06, lenof(OID_szOID_CTL), OID_szOID_CTL)) || (embedded && asn1_expect_obj(map, &asn1.content, &asn1.size, 0x06, lenof(OID_SPC_INDIRECT_DATA_OBJID), OID_SPC_INDIRECT_DATA_OBJID)) ) break; if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0xa0)) break; if(asn1.size) { cli_dbgmsg("asn1_parse_mscat: found extra data in contentInfo\n"); break; } dsize = deep.size; if(asn1_expect_objtype(map, deep.content, &dsize, &deep, 0x30)) break; if(dsize) { cli_dbgmsg("asn1_parse_mscat: found extra data in content\n"); break; } *hashes = deep.content; *hashes_size = deep.size; if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa0)) /* certificates */ break; dsize = asn1.size; if(dsize) { crtmgr newcerts; crtmgr_init(&newcerts); while(dsize) { if(asn1_get_x509(map, &asn1.content, &dsize, cmgr, &newcerts)) { dsize = 1; break; } } if(dsize) break; if(newcerts.crts) { x509 = newcerts.crts; cli_dbgmsg("asn1_parse_mscat: %u new certificates collected\n", newcerts.items); while(x509) { cli_crt *parent = crtmgr_verify_crt(cmgr, x509); /* Dump the cert if requested before anything happens to it */ if (engine->dconf->pe & PE_CONF_DUMPCERT) { char issuer[SHA1_HASH_SIZE*2+1], subject[SHA1_HASH_SIZE*2+1], serial[SHA1_HASH_SIZE*2+1]; char mod[1024], exp[1024]; int j=1024; fp_toradix_n(&x509->n, mod, 16, j); fp_toradix_n(&x509->e, exp, 16, j); for (j=0; j < SHA1_HASH_SIZE; j++) { sprintf(&issuer[j*2], "%02x", x509->issuer[j]); sprintf(&subject[j*2], "%02x", x509->subject[j]); sprintf(&serial[j*2], "%02x", x509->serial[j]); } cli_dbgmsg_internal("cert subject:%s serial:%s pubkey:%s i:%s %lu->%lu %s %s %s\n", subject, serial, mod, issuer, (unsigned long)x509->not_before, (unsigned long)x509->not_after, x509->certSign ? "cert" : "", x509->codeSign ? "code" : "", x509->timeSign ? "time" : ""); } if(parent) { if (parent->isBlacklisted) { isBlacklisted = 1; cli_dbgmsg("asn1_parse_mscat: Authenticode certificate %s is revoked. Flagging sample as virus.\n", (parent->name ? parent->name : "(no name)")); } x509->codeSign &= parent->codeSign; x509->timeSign &= parent->timeSign; if(crtmgr_add(cmgr, x509)) break; crtmgr_del(&newcerts, x509); x509 = newcerts.crts; continue; } x509 = x509->next; } if(x509) break; if(newcerts.items) cli_dbgmsg("asn1_parse_mscat: %u certificates did not verify\n", newcerts.items); crtmgr_free(&newcerts); } } if(asn1_get_obj(map, asn1.next, &size, &asn1)) break; if(asn1.type == 0xa1 && asn1_get_obj(map, asn1.next, &size, &asn1)) /* crls - unused shouldn't be present */ break; if(asn1.type != 0x31) { /* signerInfos */ cli_dbgmsg("asn1_parse_mscat: unexpected type %02x for signerInfos\n", asn1.type); break; } if(size) { cli_dbgmsg("asn1_parse_mscat: unexpected extra data after signerInfos\n"); break; } size = asn1.size; if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) break; if(size) { cli_dbgmsg("asn1_parse_mscat: only one signerInfo shall be present\n"); break; } size = asn1.size; if(asn1_expect_obj(map, &asn1.content, &size, 0x02, 1, "\x01")) /* Version = 1 */ break; if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) /* issuerAndSerialNumber */ break; dsize = asn1.size; if(asn1_expect_objtype(map, asn1.content, &dsize, &deep, 0x30)) /* issuer */ break; if(map_sha1(map, deep.content, deep.size, issuer)) break; if(asn1_expect_objtype(map, deep.next, &dsize, &deep, 0x02)) /* serial */ break; if(map_sha1(map, deep.content, deep.size, serial)) break; if(dsize) { cli_dbgmsg("asn1_parse_mscat: extra data inside issuerAndSerialNumber\n"); break; } if(asn1_expect_algo(map, &asn1.next, &size, lenof(OID_sha1), OID_sha1)) /* digestAlgorithm == sha1 */ break; attrs = asn1.next; if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa0)) /* authenticatedAttributes */ break; attrs_size = (uint8_t *)(asn1.next) - attrs; if(attrs_size < 2) { cli_dbgmsg("asn1_parse_mscat: authenticatedAttributes size is too small\n"); break; } dsize = asn1.size; deep.next = asn1.content; result = 0; while(dsize) { struct cli_asn1 cobj; int content; if(asn1_expect_objtype(map, deep.next, &dsize, &deep, 0x30)) { /* attribute */ dsize = 1; break; } if(asn1_expect_objtype(map, deep.content, &deep.size, &deeper, 0x06)) { /* attribute type */ dsize = 1; break; } if(deeper.size != lenof(OID_contentType)) continue; if(!fmap_need_ptr_once(map, deeper.content, lenof(OID_contentType))) { cli_dbgmsg("asn1_parse_mscat: failed to read authenticated attribute\n"); dsize = 1; break; } if(!memcmp(deeper.content, OID_contentType, lenof(OID_contentType))) content = 0; /* contentType */ else if(!memcmp(deeper.content, OID_messageDigest, lenof(OID_messageDigest))) content = 1; /* messageDigest */ else continue; if(asn1_expect_objtype(map, deeper.next, &deep.size, &deeper, 0x31)) { /* set - contents */ dsize = 1; break; } if(deep.size) { cli_dbgmsg("asn1_parse_mscat: extra data in authenticated attributes\n"); dsize = 1; break; } if(result & (1<<content)) { cli_dbgmsg("asn1_parse_mscat: contentType or messageDigest appear twice\n"); dsize = 1; break; } if(content == 0) { /* contentType */ if( (!embedded && asn1_expect_obj(map, &deeper.content, &deeper.size, 0x06, lenof(OID_szOID_CTL), OID_szOID_CTL)) || /* cat file */ (embedded && asn1_expect_obj(map, &deeper.content, &deeper.size, 0x06, lenof(OID_SPC_INDIRECT_DATA_OBJID), OID_SPC_INDIRECT_DATA_OBJID)) /* embedded cat */ ) { dsize = 1; break; } result |= 1; } else { /* messageDigest */ if(asn1_expect_objtype(map, deeper.content, &deeper.size, &cobj, 0x04)) { dsize = 1; break; } if(cobj.size != SHA1_HASH_SIZE) { cli_dbgmsg("asn1_parse_mscat: messageDigest attribute has got the wrong size (%u)\n", cobj.size); dsize = 1; break; } if(!fmap_need_ptr_once(map, cobj.content, SHA1_HASH_SIZE)) { cli_dbgmsg("asn1_parse_mscat: failed to read authenticated attribute\n"); dsize = 1; break; } memcpy(md, cobj.content, SHA1_HASH_SIZE); result |= 2; } if(deeper.size) { cli_dbgmsg("asn1_parse_mscat: extra data in authenticated attribute\n"); dsize = 1; break; } } if(dsize) break; if(result != 3) { cli_dbgmsg("asn1_parse_mscat: contentType or messageDigest are missing\n"); break; } if(asn1_expect_algo(map, &asn1.next, &size, lenof(OID_rsaEncryption), OID_rsaEncryption)) /* digestEncryptionAlgorithm == sha1 */ break; if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x04)) /* encryptedDigest */ break; if(asn1.size > 513) { cli_dbgmsg("asn1_parse_mscat: encryptedDigest too long\n"); break; } if(map_sha1(map, *hashes, *hashes_size, sha1)) break; if(memcmp(sha1, md, sizeof(sha1))) { cli_dbgmsg("asn1_parse_mscat: messageDigest mismatch\n"); break; } if(!fmap_need_ptr_once(map, attrs, attrs_size)) { cli_dbgmsg("asn1_parse_mscat: failed to read authenticatedAttributes\n"); break; } ctx = cl_hash_init("sha1"); if (!(ctx)) break; cl_update_hash(ctx, "\x31", 1); cl_update_hash(ctx, (void *)(attrs + 1), attrs_size - 1); cl_finish_hash(ctx, sha1); if(!fmap_need_ptr_once(map, asn1.content, asn1.size)) { cli_dbgmsg("asn1_parse_mscat: failed to read encryptedDigest\n"); break; } if(!(x509 = crtmgr_verify_pkcs7(cmgr, issuer, serial, asn1.content, asn1.size, CLI_SHA1RSA, sha1, VRFY_CODE))) { cli_dbgmsg("asn1_parse_mscat: pkcs7 signature verification failed\n"); break; } message = asn1.content; message_size = asn1.size; if(!size) { cli_dbgmsg("asn1_parse_mscat: countersignature is missing\n"); break; } if(size && asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa1)) /* unauthenticatedAttributes */ break; if(size) { cli_dbgmsg("asn1_parse_mscat: extra data inside signerInfo\n"); break; } size = asn1.size; if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) break; if(size) { cli_dbgmsg("asn1_parse_mscat: extra data inside unauthenticatedAttributes\n"); break; } size = asn1.size; /* 1.2.840.113549.1.9.6 - counterSignature */ if(asn1_expect_obj(map, &asn1.content, &size, 0x06, lenof(OID_countersignature), OID_countersignature)) break; if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x31)) break; if(size) { cli_dbgmsg("asn1_parse_mscat: extra data inside counterSignature\n"); break; } size = asn1.size; if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) break; if(size) { cli_dbgmsg("asn1_parse_mscat: extra data inside unauthenticatedAttributes\n"); break; } size = asn1.size; if(asn1_expect_obj(map, &asn1.content, &size, 0x02, 1, "\x01")) /* Version = 1*/ break; if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) /* issuerAndSerialNumber */ break; if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0x30)) /* issuer */ break; if(map_sha1(map, deep.content, deep.size, issuer)) break; if(asn1_expect_objtype(map, deep.next, &asn1.size, &deep, 0x02)) /* serial */ break; if(map_sha1(map, deep.content, deep.size, serial)) break; if(asn1.size) { cli_dbgmsg("asn1_parse_mscat: extra data inside countersignature issuer\n"); break; } if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x30)) /* digestAlgorithm */ break; if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0x06)) break; if(deep.size != lenof(OID_sha1) && deep.size != lenof(OID_md5)) { cli_dbgmsg("asn1_parse_mscat: wrong digestAlgorithm size\n"); break; } if(!fmap_need_ptr_once(map, deep.content, deep.size)) { cli_dbgmsg("asn1_parse_mscat: failed to read digestAlgorithm OID\n"); break; } if(deep.size == lenof(OID_sha1) && !memcmp(deep.content, OID_sha1, lenof(OID_sha1))) { hashtype = CLI_SHA1RSA; if(map_sha1(map, message, message_size, md)) break; } else if(deep.size == lenof(OID_md5) && !memcmp(deep.content, OID_md5, lenof(OID_md5))) { hashtype = CLI_MD5RSA; if(map_md5(map, message, message_size, md)) break; } else { cli_dbgmsg("asn1_parse_mscat: unknown digest oid in countersignature\n"); break; } if(asn1.size && asn1_expect_obj(map, &deep.next, &asn1.size, 0x05, 0, NULL)) break; if(asn1.size) { cli_dbgmsg("asn1_parse_mscat: extra data in countersignature oid\n"); break; } attrs = asn1.next; if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa0)) /* authenticatedAttributes */ break; attrs_size = (uint8_t *)(asn1.next) - attrs; if(attrs_size < 2) { cli_dbgmsg("asn1_parse_mscat: countersignature authenticatedAttributes are too small\n"); break; } result = 0; dsize = asn1.size; deep.next = asn1.content; while(dsize) { int content; if(asn1_expect_objtype(map, deep.next, &dsize, &deep, 0x30)) { /* attribute */ dsize = 1; break; } if(asn1_expect_objtype(map, deep.content, &deep.size, &deeper, 0x06)) { /* attribute type */ dsize = 1; break; } if(deeper.size != lenof(OID_contentType)) /* lenof(contentType) = lenof(messageDigest) = lenof(signingTime) = 9 */ continue; if(!fmap_need_ptr_once(map, deeper.content, lenof(OID_contentType))) { dsize = 1; break; } if(!memcmp(deeper.content, OID_contentType, lenof(OID_contentType))) content = 0; /* contentType */ else if(!memcmp(deeper.content, OID_messageDigest, lenof(OID_messageDigest))) content = 1; /* messageDigest */ else if(!memcmp(deeper.content, OID_signingTime, lenof(OID_signingTime))) content = 2; /* signingTime */ else continue; if(result & (1<<content)) { cli_dbgmsg("asn1_parse_mscat: duplicate field in countersignature\n"); dsize = 1; break; } result |= (1<<content); if(asn1_expect_objtype(map, deeper.next, &deep.size, &deeper, 0x31)) { /* attribute type */ dsize = 1; break; } if(deep.size) { cli_dbgmsg("asn1_parse_mscat: extra data in countersignature value\n"); dsize = 1; break; } deep.size = deeper.size; switch(content) { case 0: /* contentType = pkcs7-data */ if(asn1_expect_obj(map, &deeper.content, &deep.size, 0x06, lenof(OID_pkcs7_data), OID_pkcs7_data)) deep.size = 1; else if(deep.size) cli_dbgmsg("asn1_parse_mscat: extra data in countersignature content-type\n"); break; case 1: /* messageDigest */ if(asn1_expect_obj(map, &deeper.content, &deep.size, 0x04, (hashtype == CLI_SHA1RSA) ? SHA1_HASH_SIZE : 16, md)) { deep.size = 1; cli_dbgmsg("asn1_parse_mscat: countersignature hash mismatch\n"); } else if(deep.size) cli_dbgmsg("asn1_parse_mscat: extra data in countersignature message-digest\n"); break; case 2: /* signingTime */ { time_t sigdate; /* FIXME shall i use it?! */ if(asn1_get_time(map, &deeper.content, &deep.size, &sigdate)) deep.size = 1; else if(deep.size) cli_dbgmsg("asn1_parse_mscat: extra data in countersignature signing-time\n"); else if(sigdate < x509->not_before || sigdate > x509->not_after) { cli_dbgmsg("asn1_parse_mscat: countersignature timestamp outside cert validity\n"); deep.size = 1; } break; } } if(deep.size) { dsize = 1; break; } } if(dsize) break; if(result != 7) { cli_dbgmsg("asn1_parse_mscat: some important attributes are missing in countersignature\n"); break; } if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x30)) /* digestEncryptionAlgorithm == sha1 */ break; if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0x06)) /* digestEncryptionAlgorithm == sha1 */ break; if(deep.size != lenof(OID_rsaEncryption)) { /* lenof(OID_rsaEncryption) = lenof(OID_sha1WithRSAEncryption) = 9 */ cli_dbgmsg("asn1_parse_mscat: wrong digestEncryptionAlgorithm size in countersignature\n"); break; } if(!fmap_need_ptr_once(map, deep.content, lenof(OID_rsaEncryption))) { cli_dbgmsg("asn1_parse_mscat: cannot read digestEncryptionAlgorithm in countersignature\n"); break; } /* rsaEncryption or sha1withRSAEncryption */ if(memcmp(deep.content, OID_rsaEncryption, lenof(OID_rsaEncryption)) && memcmp(deep.content, OID_sha1WithRSAEncryption, lenof(OID_sha1WithRSAEncryption))) { cli_dbgmsg("asn1_parse_mscat: digestEncryptionAlgorithm in countersignature is not sha1\n"); break; } if(asn1.size && asn1_expect_obj(map, &deep.next, &asn1.size, 0x05, 0, NULL)) break; if(asn1.size) { cli_dbgmsg("asn1_parse_mscat: extra data in digestEncryptionAlgorithm in countersignature\n"); break; } if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x04)) /* encryptedDigest */ break; if(asn1.size > 513) { cli_dbgmsg("asn1_parse_mscat: countersignature encryptedDigest too long\n"); break; } if(size) { cli_dbgmsg("asn1_parse_mscat: extra data inside countersignature\n"); break; } if(!fmap_need_ptr_once(map, attrs, attrs_size)) { cli_dbgmsg("asn1_parse_mscat: failed to read authenticatedAttributes\n"); break; } if(hashtype == CLI_SHA1RSA) { ctx = cl_hash_init("sha1"); if (!(ctx)) break; cl_update_hash(ctx, "\x31", 1); cl_update_hash(ctx, (void *)(attrs + 1), attrs_size - 1); cl_finish_hash(ctx, sha1); } else { ctx = cl_hash_init("md5"); if (!(ctx)) break; cl_update_hash(ctx, "\x31", 1); cl_update_hash(ctx, (void *)(attrs + 1), attrs_size - 1); cl_finish_hash(ctx, sha1); } if(!fmap_need_ptr_once(map, asn1.content, asn1.size)) { cli_dbgmsg("asn1_parse_mscat: failed to read countersignature encryptedDigest\n"); break; } if(!crtmgr_verify_pkcs7(cmgr, issuer, serial, asn1.content, asn1.size, hashtype, sha1, VRFY_TIME)) { cli_dbgmsg("asn1_parse_mscat: pkcs7 countersignature verification failed\n"); break; } cli_dbgmsg("asn1_parse_mscat: catalog successfully parsed\n"); if (isBlacklisted) { return 1; } return 0; } while(0); cli_dbgmsg("asn1_parse_mscat: failed to parse catalog\n"); return 1; }
php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, php_http_message_t **message) { char *str = NULL; size_t len = 0; size_t cut = 0; while (buffer->used || !php_http_message_parser_states[php_http_message_parser_state_is(parser)].need_data) { #if DBG_PARSER fprintf(stderr, "#MP: %s (f: %u, t:%d, l:%zu)\n", php_http_message_parser_state_name(php_http_message_parser_state_is(parser)), flags, message && *message ? (*message)->type : -1, buffer->used ); _dpf(0, buffer->data, buffer->used); #endif switch (php_http_message_parser_state_pop(parser)) { case PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE: return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE); case PHP_HTTP_MESSAGE_PARSER_STATE_START: { char *ptr = buffer->data; while (ptr - buffer->data < buffer->used && PHP_HTTP_IS_CTYPE(space, *ptr)) { ++ptr; } php_http_buffer_cut(buffer, 0, ptr - buffer->data); if (buffer->used) { php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER); } break; } case PHP_HTTP_MESSAGE_PARSER_STATE_HEADER: { unsigned header_parser_flags = (flags & PHP_HTTP_MESSAGE_PARSER_CLEANUP) ? PHP_HTTP_HEADER_PARSER_CLEANUP : 0; switch (php_http_header_parser_parse(&parser->header, buffer, header_parser_flags, *message ? &(*message)->hdrs : NULL, (php_http_info_callback_t) php_http_message_info_callback, message)) { case PHP_HTTP_HEADER_PARSER_STATE_FAILURE: return PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE; case PHP_HTTP_HEADER_PARSER_STATE_DONE: php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE); break; default: if (buffer->used || !(flags & PHP_HTTP_MESSAGE_PARSER_CLEANUP)) { return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER); } else { php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE); } } break; } case PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE: { zval h, *h_ptr, *h_loc = NULL, *h_con = NULL, *h_ce; zend_bool chunked = 0; zend_long content_length = -1; zend_string *content_range = NULL; /* Content-Range has higher precedence than Content-Length, * and content-length denotes the original length of the entity, * so let's *NOT* remove CR/CL, because that would fundamentally * change the meaning of the whole message */ if ((h_ptr = php_http_message_header(*message, ZEND_STRL("Transfer-Encoding")))) { zend_string *zs = zval_get_string(h_ptr); chunked = zend_string_equals_literal(zs, "chunked"); zend_string_release(zs); Z_TRY_ADDREF_P(h_ptr); zend_hash_str_update(&(*message)->hdrs, "X-Original-Transfer-Encoding", lenof("X-Original-Transfer-Encoding"), h_ptr); zend_hash_str_del(&(*message)->hdrs, "Transfer-Encoding", lenof("Transfer-Encoding")); /* reset */ ZVAL_LONG(&h, 0); zend_hash_str_update(&(*message)->hdrs, "Content-Length", lenof("Content-Length"), &h); } else if ((h_ptr = php_http_message_header(*message, ZEND_STRL("Content-Length")))) { content_length = zval_get_long(h_ptr); Z_TRY_ADDREF_P(h_ptr); zend_hash_str_update(&(*message)->hdrs, "X-Original-Content-Length", lenof("X-Original-Content-Length"), h_ptr); } if ((content_range = php_http_message_header_string(*message, ZEND_STRL("Content-Range")))) { ZVAL_STR_COPY(&h, content_range); zend_hash_str_update(&(*message)->hdrs, "Content-Range", lenof("Content-Range"), &h); } /* so, if curl sees a 3xx code, a Location header and a Connection:close header * it decides not to read the response body. */ if ((flags & PHP_HTTP_MESSAGE_PARSER_EMPTY_REDIRECTS) && (*message)->type == PHP_HTTP_RESPONSE && (*message)->http.info.response.code/100 == 3 && (h_loc = php_http_message_header(*message, ZEND_STRL("Location"))) && (h_con = php_http_message_header(*message, ZEND_STRL("Connection"))) ) { zend_string *con = zval_get_string(h_con); if (php_http_match(con->val, "close", PHP_HTTP_MATCH_WORD)) { zend_string_release(con); php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_DONE); break; } zend_string_release(con); } if ((h_ce = php_http_message_header(*message, ZEND_STRL("Content-Encoding")))) { zend_string *ce = zval_get_string(h_ce); if (php_http_match(ce->val, "gzip", PHP_HTTP_MATCH_WORD) || php_http_match(ce->val, "x-gzip", PHP_HTTP_MATCH_WORD) || php_http_match(ce->val, "deflate", PHP_HTTP_MATCH_WORD) ) { if (parser->inflate) { php_http_encoding_stream_reset(&parser->inflate); } else { parser->inflate = php_http_encoding_stream_init(NULL, php_http_encoding_stream_get_inflate_ops(), 0); } Z_TRY_ADDREF_P(h_ce); zend_hash_str_update(&(*message)->hdrs, "X-Original-Content-Encoding", lenof("X-Original-Content-Encoding"), h_ce); zend_hash_str_del(&(*message)->hdrs, "Content-Encoding", lenof("Content-Encoding")); } zend_string_release(ce); } if ((flags & PHP_HTTP_MESSAGE_PARSER_DUMB_BODIES)) { php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB); } else { if (chunked) { parser->dechunk = php_http_encoding_stream_init(parser->dechunk, php_http_encoding_stream_get_dechunk_ops(), 0); php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED); break; } if (content_range) { ulong total = 0, start = 0, end = 0; if (!strncasecmp(content_range->val, "bytes", lenof("bytes")) && ( content_range->val[lenof("bytes")] == ':' || content_range->val[lenof("bytes")] == ' ' || content_range->val[lenof("bytes")] == '=' ) ) { char *total_at = NULL, *end_at = NULL; char *start_at = content_range->val + sizeof("bytes"); start = strtoul(start_at, &end_at, 10); if (end_at) { end = strtoul(end_at + 1, &total_at, 10); if (total_at && strncmp(total_at + 1, "*", 1)) { total = strtoul(total_at + 1, NULL, 10); } if (end >= start && (!total || end <= total)) { parser->body_length = end + 1 - start; php_http_message_parser_state_push(parser, 1, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH); zend_string_release(content_range); break; } } } zend_string_release(content_range); } if (content_length >= 0) { parser->body_length = content_length; php_http_message_parser_state_push(parser, 1, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH); break; } if ((*message)->type == PHP_HTTP_REQUEST) { php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_DONE); } else { php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB); } } break; } case PHP_HTTP_MESSAGE_PARSER_STATE_BODY: { if (len) { if (parser->inflate) { char *dec_str = NULL; size_t dec_len; if (SUCCESS != php_http_encoding_stream_update(parser->inflate, str, len, &dec_str, &dec_len)) { return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE); } if (str != buffer->data) { PTR_FREE(str); } str = dec_str; len = dec_len; } php_stream_write(php_http_message_body_stream((*message)->body), str, len); } if (cut) { php_http_buffer_cut(buffer, 0, cut); } if (str != buffer->data) { PTR_FREE(str); } str = NULL; len = 0; cut = 0; break; } case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB: { str = buffer->data; len = buffer->used; cut = len; php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE, PHP_HTTP_MESSAGE_PARSER_STATE_BODY); break; } case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH: { len = MIN(parser->body_length, buffer->used); str = buffer->data; cut = len; parser->body_length -= len; php_http_message_parser_state_push(parser, 2, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH, PHP_HTTP_MESSAGE_PARSER_STATE_BODY); break; } case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED: { /* * - pass available data through the dechunk stream * - pass decoded data along * - if stream zeroed: * Y: - cut processed string out of buffer, but leave length of unprocessed dechunk stream data untouched * - body done * N: - parse ahaed */ char *dec_str = NULL; size_t dec_len; if (SUCCESS != php_http_encoding_stream_update(parser->dechunk, buffer->data, buffer->used, &dec_str, &dec_len)) { return PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE; } str = dec_str; len = dec_len; if (php_http_encoding_stream_done(parser->dechunk)) { cut = buffer->used - PHP_HTTP_BUFFER(parser->dechunk->ctx)->used; php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE, PHP_HTTP_MESSAGE_PARSER_STATE_BODY); } else { cut = buffer->used; php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED, PHP_HTTP_MESSAGE_PARSER_STATE_BODY); } break; } case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE: { php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_DONE); if (parser->dechunk && parser->dechunk->ctx) { char *dec_str = NULL; size_t dec_len; if (SUCCESS != php_http_encoding_stream_finish(parser->dechunk, &dec_str, &dec_len)) { return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE); } php_http_encoding_stream_dtor(parser->dechunk); if (dec_str && dec_len) { str = dec_str; len = dec_len; cut = 0; php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL, PHP_HTTP_MESSAGE_PARSER_STATE_BODY); } } break; } case PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL: { zval zcl; ZVAL_LONG(&zcl, php_http_message_body_size((*message)->body)); zend_hash_str_update(&(*message)->hdrs, "Content-Length", lenof("Content-Length"), &zcl); break; } case PHP_HTTP_MESSAGE_PARSER_STATE_DONE: { char *ptr = buffer->data; while (ptr - buffer->data < buffer->used && PHP_HTTP_IS_CTYPE(space, *ptr)) { ++ptr; } php_http_buffer_cut(buffer, 0, ptr - buffer->data); if (!(flags & PHP_HTTP_MESSAGE_PARSER_GREEDY)) { return PHP_HTTP_MESSAGE_PARSER_STATE_DONE; } break; } } } return php_http_message_parser_state_is(parser); }
void handle_request(worker_type_t wtype) { const char *param, *p_method, *p_uri; char *argp; unsigned int plen; int cluster_readonly = 0, s2sreq = 0; if(sx_hashfs_cluster_get_mode(hashfs, &cluster_readonly)) { CRIT("Failed to get cluster operating mode"); quit_errmsg(500, "Internal error: failed to check cluster operating mode"); } if(sx_hashfs_distcheck(hashfs) < 0) { CRIT("Failed to reload distribution"); quit_errmsg(503, "Internal error: failed to load distribution"); } if(sx_hashfs_is_orphan(hashfs)) quit_errmsg(410, "This node is no longer a cluster member"); msg_new_id(); verb = VERB_UNSUP; p_method = FCGX_GetParam("REQUEST_METHOD", envp); if(p_method) { plen = strlen(p_method); switch(plen) { case 3: if(!memcmp(p_method, "GET", 4)) verb = VERB_GET; else if(!memcmp(p_method, "PUT", 4)) verb = VERB_PUT; break; case 4: if(!memcmp(p_method, "HEAD", 5)) verb = VERB_HEAD; else if(!memcmp(p_method, "POST", 5)) verb = VERB_POST; break; case 6: if(!memcmp(p_method, "DELETE", 7)) verb = VERB_DELETE; break; case 7: if(!memcmp(p_method, "OPTIONS", 8)) { CGI_PUTS("Allow: GET,HEAD,OPTIONS,PUT,DELETE\r\nContent-Length: 0\r\n\r\n"); return; } break; } } if(verb == VERB_UNSUP) quit_errmsg(405, "Method Not Allowed"); if(content_len()<0 || (verb != VERB_PUT && content_len())) quit_errmsg(400, "Invalid Content-Length: must be positive and method must be PUT"); p_uri = param = FCGX_GetParam("REQUEST_URI", envp); if(!p_uri) quit_errmsg(400, "No URI provided"); plen = strlen(p_uri); if(*p_uri != '/') quit_errmsg(400, "URI must start with /"); if(plen > sizeof(reqbuf) - 1) quit_errmsg(414, "URL too long: request line must be <8k"); do { param++; plen--; } while(*param == '/'); if(!strncmp(param, ".s2s/", lenof(".s2s/"))) { param += lenof(".s2s/"); plen -= lenof(".s2s/"); while(*param == '/') { param++; plen--; } s2sreq = 1; } if(wtype == WORKER_S2S && !s2sreq) WARN("Misconfiguration detected. Please make sure your restricted-socket config option is properly set."); /* FIXME: we could detect the opposite kind of mismatch * at the cost of extra complications in the wtype definition * I prefer to privilege simplicity at this point */ memcpy(reqbuf, param, plen+1); argp = memchr(reqbuf, '?', plen); nargs = 0; if(argp) { unsigned int argslen = plen - (argp - reqbuf); plen = argp - reqbuf; do { *argp = '\0'; argp++; argslen--; } while(*argp == '?'); if(!argslen) argp = NULL; else { do { char *nextarg; if(nargs >= MAX_ARGS) quit_errmsg(414, "Too many parameters"); nextarg = memchr(argp, '&', argslen); if(nextarg) { do { *nextarg = '\0'; nextarg++; } while(*nextarg == '&'); } if(*argp) { if(!(args[nargs] = inplace_urldecode(argp, 0, 0, NULL, 1))) quit_errmsg(400, "Invalid URL encoding"); if(sxi_utf8_validate_len(args[nargs]) < 0) quit_errmsg(400, "Parameters with invalid utf-8 encoding"); nargs++; } argslen -= nextarg - argp; argp = nextarg; } while (argp); } } while(plen && reqbuf[plen-1] == '/') { plen--; reqbuf[plen] = '\0'; } path = memchr(reqbuf, '/', plen); if(path) { do { *path = '\0'; path ++; } while(*path == '/'); if(!*path) path = NULL; } volume = *reqbuf ? reqbuf : NULL; int forbidden = 0; if((volume && !inplace_urldecode(volume, '/', 0, &forbidden, 0)) || (path && !inplace_urldecode(path, '/', '/', &forbidden, 0))) { if (forbidden) quit_errmsg(400, "Volume or path with forbidden %2f or %00"); else quit_errmsg(400, "Invalid URL encoding"); } int vlen = volume ? sxi_utf8_validate_len(volume) : 0; int flen = path ? strlen(path) : 0; if (vlen < 0 || flen < 0) quit_errmsg(400, "URL with invalid utf-8 encoding"); if (is_reserved()) { /* No UTF8/url-encoding used on reserved volumes, allow higher limit. * Otherwise we hit the 1024 limit with batch requests already */ if (path && strlen(path) > SXLIMIT_MAX_FILENAME_LEN * 3) { msg_set_reason("Path too long: filename must be <%d bytes (%ld)", SXLIMIT_MAX_FILENAME_LEN*3+ 1, strlen(path)); quit_errmsg(414, msg_get_reason()); } } else { if (flen > SXLIMIT_MAX_FILENAME_LEN) { msg_set_reason("Path too long: filename must be <%d bytes (%d)", SXLIMIT_MAX_FILENAME_LEN + 1, flen); quit_errmsg(414, msg_get_reason()); } } if (volume && strlen(volume) > SXLIMIT_MAX_VOLNAME_LEN) { msg_set_reason("Volume name too long: must be <= %d bytes", SXLIMIT_MAX_VOLNAME_LEN); quit_errmsg(414, msg_get_reason()); } body_ctx = sxi_md_init(); if (!body_ctx || !sxi_sha1_init(body_ctx)) quit_errmsg(500, "Failed to initialize crypto engine"); hmac_ctx = sxi_hmac_sha1_init(); if (!hmac_ctx) quit_errmsg(503, "Cannot initialize crypto library"); authed = AUTH_NOTAUTH; role = PRIV_NONE; /* Begin auth check */ uint8_t buf[AUTHTOK_BIN_LEN], key[AUTH_KEY_LEN]; unsigned int blen = sizeof(buf); time_t reqdate, now; param = FCGX_GetParam("HTTP_AUTHORIZATION", envp); if(!param || strlen(param) != lenof("SKY ") + AUTHTOK_ASCII_LEN || strncmp(param, "SKY ", 4)) { if(volume) { send_authreq(); return; } quit_home(); } if(sxi_b64_dec_core(param+4, buf, &blen) || blen != sizeof(buf)) { send_authreq(); return; } memcpy(user, buf, sizeof(user)); memcpy(rhmac, buf+20, sizeof(rhmac)); if(sx_hashfs_get_user_info(hashfs, user, &uid, key, &role, NULL, &user_quota) != OK) /* no such user */ { DEBUG("No such user: %s", param+4); send_authreq(); return; } DEBUG("Request from uid %lld", (long long)uid); if(cluster_readonly && (verb == VERB_PUT || verb == VERB_DELETE) && !has_priv(PRIV_CLUSTER) && !has_priv(PRIV_ADMIN)) quit_errmsg(503, "Cluster is in read-only mode"); if(s2sreq && !has_priv(PRIV_CLUSTER)) { send_authreq(); return; } if(!sxi_hmac_sha1_init_ex(hmac_ctx, key, sizeof(key))) { WARN("hmac_init failed"); quit_errmsg(500, "Failed to initialize crypto engine"); } if(!sxi_hmac_sha1_update_str(hmac_ctx, p_method)) quit_errmsg(500, "Crypto error authenticating the request"); if(!sxi_hmac_sha1_update_str(hmac_ctx, p_uri+1)) quit_errmsg(500, "Crypto error authenticating the request"); param = FCGX_GetParam("HTTP_DATE", envp); if(!param) quit_errmsg(400, "Missing Date: header"); if(httpdate_to_time_t(param, &reqdate)) quit_errmsg(400, "Date header in wrong format"); now = time(NULL); if(reqdate < now - MAX_CLOCK_DRIFT * 60 || reqdate > now + MAX_CLOCK_DRIFT * 60) { CGI_PUTS("WWW-Authenticate: SKY realm=\"SXCLOCK\"\r\n"); quit_errmsg(401, "Client clock drifted more than "STRIFY(MAX_CLOCK_DRIFT)" minutes"); } if(!sxi_hmac_sha1_update_str(hmac_ctx, param)) quit_errmsg(500, "Crypto error authenticating the request"); if(!content_len()) { /* If no body is present, complete authentication now */ uint8_t chmac[20]; unsigned int chmac_len = 20; if(!sxi_hmac_sha1_update_str(hmac_ctx, "da39a3ee5e6b4b0d3255bfef95601890afd80709")) quit_errmsg(500, "Crypto error authenticating the request"); if(!sxi_hmac_sha1_final(hmac_ctx, chmac, &chmac_len)) quit_errmsg(500, "Crypto error authenticating the request"); if(!hmac_compare(chmac, rhmac, sizeof(rhmac))) { authed = AUTH_OK; } else { /* WARN("auth mismatch"); */ send_authreq(); return; } } else /* Otherwise set it as pending */ authed = AUTH_BODYCHECK; if(has_priv(PRIV_CLUSTER) && sx_hashfs_uses_secure_proto(hashfs) != is_https() && !sx_storage_is_bare(hashfs)) { /* programmed nodes: must obey cluster SSL mode * unprogrammed nodes: can use SSL instead of non-SSL, * it is the cluster's responsibility to initiate programming via SSL, * as the unprogrammed node would accept both * * */ WARN("hashfs use-ssl: %d, https: %d, is_bare: %d", sx_hashfs_uses_secure_proto(hashfs), is_https(), sx_storage_is_bare(hashfs)); quit_errmsg(403, sx_hashfs_uses_secure_proto(hashfs) ? "Cluster operations require SECURE mode" : "Cluster operations require INSECURE mode"); } if(!volume) cluster_ops(); else if(!path) volume_ops(); else file_ops(); if(authed == AUTH_BODYCHECKING) DEBUG("Bad request signature"); sxi_hmac_sha1_cleanup(&hmac_ctx); sxi_md_cleanup(&body_ctx); }
int do_eventsel_loop(HANDLE other_event) { int n, nhandles, nallhandles, netindex, otherindex; long next, ticks; HANDLE *handles; SOCKET *sklist; int skcount; long now = GETTICKCOUNT(); static int timeoutCount = 0; if (sk_isClosed()) { return -1; } if (run_timers(now, &next)) { ticks = next - GETTICKCOUNT(); if (ticks < 0) ticks = 0; /* just in case */ } else { ticks = INFINITE; } if (ticks < 0 || ticks > 100) ticks = 100; handles = handle_get_events(&nhandles); handles = sresize(handles, nhandles+2, HANDLE); nallhandles = nhandles; if (netevent != INVALID_HANDLE_VALUE) handles[netindex = nallhandles++] = netevent; else netindex = -1; if (other_event != INVALID_HANDLE_VALUE) handles[otherindex = nallhandles++] = other_event; else otherindex = -1; n = WaitForMultipleObjects(nallhandles, handles, FALSE, ticks); if (STATUS_TIMEOUT == n) { sfree(handles); ++timeoutCount; return timeoutCount > 50 ? -1 : 0; } timeoutCount = 0; if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) { handle_got_event(handles[n - WAIT_OBJECT_0]); } else if (netindex >= 0 && n == WAIT_OBJECT_0 + netindex) { WSANETWORKEVENTS things; SOCKET socket; extern SOCKET first_socket(int *), next_socket(int *); extern int select_result(WPARAM, LPARAM); int i, socketstate; /* * We must not call select_result() for any socket * until we have finished enumerating within the * tree. This is because select_result() may close * the socket and modify the tree. */ /* Count the active sockets. */ i = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) i++; /* Expand the buffer if necessary. */ sklist = snewn(i, SOCKET); /* Retrieve the sockets into sklist. */ skcount = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) { sklist[skcount++] = socket; } /* Now we're done enumerating; go through the list. */ for (i = 0; i < skcount; i++) { WPARAM wp; socket = sklist[i]; wp = (WPARAM) socket; if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) { static const struct { int bit, mask; } eventtypes[] = { {FD_CONNECT_BIT, FD_CONNECT}, {FD_READ_BIT, FD_READ}, {FD_CLOSE_BIT, FD_CLOSE}, {FD_OOB_BIT, FD_OOB}, {FD_WRITE_BIT, FD_WRITE}, {FD_ACCEPT_BIT, FD_ACCEPT}, }; int e; noise_ultralight(socket); noise_ultralight(things.lNetworkEvents); for (e = 0; e < lenof(eventtypes); e++) if (things.lNetworkEvents & eventtypes[e].mask) { LPARAM lp; int err = things.iErrorCode[eventtypes[e].bit]; lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err); select_result(wp, lp); } } } sfree(sklist); } sfree(handles); if (n == WAIT_TIMEOUT) { now = next; } else { now = GETTICKCOUNT(); } if (otherindex >= 0 && n == WAIT_OBJECT_0 + otherindex) return 1; return 0; }
SockAddr *sk_namelookup(const char *host, char **canonicalname, int address_family) { SockAddr *ret = snew(SockAddr); unsigned long a; char realhost[8192]; int hint_family; /* Default to IPv4. */ hint_family = (address_family == ADDRTYPE_IPV4 ? AF_INET : #ifndef NO_IPV6 address_family == ADDRTYPE_IPV6 ? AF_INET6 : #endif AF_UNSPEC); /* Clear the structure and default to IPv4. */ memset(ret, 0, sizeof(SockAddr)); #ifndef NO_IPV6 ret->ais = NULL; #endif ret->namedpipe = false; ret->addresses = NULL; ret->resolved = false; ret->refcount = 1; *realhost = '\0'; if ((a = p_inet_addr(host)) == (unsigned long) INADDR_NONE) { struct hostent *h = NULL; int err = 0; #ifndef NO_IPV6 /* * Use getaddrinfo when it's available */ if (p_getaddrinfo) { struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = hint_family; hints.ai_flags = AI_CANONNAME; { /* strip [] on IPv6 address literals */ char *trimmed_host = host_strduptrim(host); err = p_getaddrinfo(trimmed_host, NULL, &hints, &ret->ais); sfree(trimmed_host); } if (err == 0) ret->resolved = true; } else #endif { /* * Otherwise use the IPv4-only gethostbyname... * (NOTE: we don't use gethostbyname as a fallback!) */ if ( (h = p_gethostbyname(host)) ) ret->resolved = true; else err = p_WSAGetLastError(); } if (!ret->resolved) { ret->error = (err == WSAENETDOWN ? "Network is down" : err == WSAHOST_NOT_FOUND ? "Host does not exist" : err == WSATRY_AGAIN ? "Host not found" : #ifndef NO_IPV6 p_getaddrinfo&&p_gai_strerror ? p_gai_strerror(err) : #endif "gethostbyname: unknown error"); } else { ret->error = NULL; #ifndef NO_IPV6 /* If we got an address info use that... */ if (ret->ais) { /* Are we in IPv4 fallback mode? */ /* We put the IPv4 address into the a variable so we can further-on use the IPv4 code... */ if (ret->ais->ai_family == AF_INET) memcpy(&a, (char *) &((SOCKADDR_IN *) ret->ais-> ai_addr)->sin_addr, sizeof(a)); if (ret->ais->ai_canonname) strncpy(realhost, ret->ais->ai_canonname, lenof(realhost)); else strncpy(realhost, host, lenof(realhost)); } /* We used the IPv4-only gethostbyname()... */ else #endif { int n; for (n = 0; h->h_addr_list[n]; n++); ret->addresses = snewn(n, unsigned long); ret->naddresses = n; for (n = 0; n < ret->naddresses; n++) { memcpy(&a, h->h_addr_list[n], sizeof(a)); ret->addresses[n] = p_ntohl(a); } memcpy(&a, h->h_addr, sizeof(a)); /* This way we are always sure the h->h_name is valid :) */ strncpy(realhost, h->h_name, sizeof(realhost)); } } } else {
void save_open_settings(void *sesskey, Config *cfg) { int i; char *p; write_setting_i(sesskey, "Present", 1); write_setting_s(sesskey, "HostName", cfg->host); write_setting_filename(sesskey, "LogFileName", cfg->logfilename); write_setting_i(sesskey, "LogType", cfg->logtype); write_setting_i(sesskey, "LogFileClash", cfg->logxfovr); write_setting_i(sesskey, "LogFlush", cfg->logflush); write_setting_i(sesskey, "SSHLogOmitPasswords", cfg->logomitpass); write_setting_i(sesskey, "SSHLogOmitData", cfg->logomitdata); p = "raw"; { const Backend *b = backend_from_proto(cfg->protocol); if (b) p = b->name; } write_setting_s(sesskey, "Protocol", p); write_setting_i(sesskey, "PortNumber", cfg->port); /* The CloseOnExit numbers are arranged in a different order from * the standard FORCE_ON / FORCE_OFF / AUTO. */ write_setting_i(sesskey, "CloseOnExit", (cfg->close_on_exit+2)%3); write_setting_i(sesskey, "WarnOnClose", !!cfg->warn_on_close); write_setting_i(sesskey, "PingInterval", cfg->ping_interval / 60); /* minutes */ write_setting_i(sesskey, "PingIntervalSecs", cfg->ping_interval % 60); /* seconds */ write_setting_i(sesskey, "TCPNoDelay", cfg->tcp_nodelay); write_setting_i(sesskey, "TCPKeepalives", cfg->tcp_keepalives); write_setting_s(sesskey, "TerminalType", cfg->termtype); write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed); wmap(sesskey, "TerminalModes", cfg->ttymodes, lenof(cfg->ttymodes)); /* Address family selection */ write_setting_i(sesskey, "AddressFamily", cfg->addressfamily); /* proxy settings */ write_setting_s(sesskey, "ProxyExcludeList", cfg->proxy_exclude_list); write_setting_i(sesskey, "ProxyDNS", (cfg->proxy_dns+2)%3); write_setting_i(sesskey, "ProxyLocalhost", cfg->even_proxy_localhost); write_setting_i(sesskey, "ProxyMethod", cfg->proxy_type); write_setting_s(sesskey, "ProxyHost", cfg->proxy_host); write_setting_i(sesskey, "ProxyPort", cfg->proxy_port); write_setting_s(sesskey, "ProxyUsername", cfg->proxy_username); write_setting_s(sesskey, "ProxyPassword", cfg->proxy_password); write_setting_s(sesskey, "ProxyTelnetCommand", cfg->proxy_telnet_command); wmap(sesskey, "Environment", cfg->environmt, lenof(cfg->environmt)); write_setting_s(sesskey, "UserName", cfg->username); write_setting_i(sesskey, "UserNameFromEnvironment", cfg->username_from_env); write_setting_s(sesskey, "LocalUserName", cfg->localusername); write_setting_i(sesskey, "NoPTY", cfg->nopty); write_setting_i(sesskey, "Compression", cfg->compression); write_setting_i(sesskey, "TryAgent", cfg->tryagent); write_setting_i(sesskey, "AgentFwd", cfg->agentfwd); write_setting_i(sesskey, "GssapiFwd", cfg->gssapifwd); write_setting_i(sesskey, "ChangeUsername", cfg->change_username); wprefs(sesskey, "Cipher", ciphernames, CIPHER_MAX, cfg->ssh_cipherlist); wprefs(sesskey, "KEX", kexnames, KEX_MAX, cfg->ssh_kexlist); write_setting_i(sesskey, "RekeyTime", cfg->ssh_rekey_time); write_setting_s(sesskey, "RekeyBytes", cfg->ssh_rekey_data); write_setting_i(sesskey, "SshNoAuth", cfg->ssh_no_userauth); write_setting_i(sesskey, "SshBanner", cfg->ssh_show_banner); write_setting_i(sesskey, "AuthTIS", cfg->try_tis_auth); write_setting_i(sesskey, "AuthKI", cfg->try_ki_auth); write_setting_i(sesskey, "AuthGSSAPI", cfg->try_gssapi_auth); #ifndef NO_GSSAPI wprefs(sesskey, "GSSLibs", gsslibkeywords, ngsslibs, cfg->ssh_gsslist); write_setting_filename(sesskey, "GSSCustom", cfg->ssh_gss_custom); #endif write_setting_i(sesskey, "SshNoShell", cfg->ssh_no_shell); write_setting_i(sesskey, "SshProt", cfg->sshprot); write_setting_s(sesskey, "LogHost", cfg->loghost); write_setting_i(sesskey, "SSH2DES", cfg->ssh2_des_cbc); write_setting_filename(sesskey, "PublicKeyFile", cfg->keyfile); write_setting_s(sesskey, "RemoteCommand", cfg->remote_cmd); write_setting_i(sesskey, "RFCEnviron", cfg->rfc_environ); write_setting_i(sesskey, "PassiveTelnet", cfg->passive_telnet); write_setting_i(sesskey, "BackspaceIsDelete", cfg->bksp_is_delete); write_setting_i(sesskey, "RXVTHomeEnd", cfg->rxvt_homeend); write_setting_i(sesskey, "LinuxFunctionKeys", cfg->funky_type); write_setting_i(sesskey, "NoApplicationKeys", cfg->no_applic_k); write_setting_i(sesskey, "NoApplicationCursors", cfg->no_applic_c); write_setting_i(sesskey, "NoMouseReporting", cfg->no_mouse_rep); write_setting_i(sesskey, "NoRemoteResize", cfg->no_remote_resize); write_setting_i(sesskey, "NoAltScreen", cfg->no_alt_screen); write_setting_i(sesskey, "NoRemoteWinTitle", cfg->no_remote_wintitle); write_setting_i(sesskey, "RemoteQTitleAction", cfg->remote_qtitle_action); write_setting_i(sesskey, "NoDBackspace", cfg->no_dbackspace); write_setting_i(sesskey, "NoRemoteCharset", cfg->no_remote_charset); write_setting_i(sesskey, "ApplicationCursorKeys", cfg->app_cursor); write_setting_i(sesskey, "ApplicationKeypad", cfg->app_keypad); write_setting_i(sesskey, "NetHackKeypad", cfg->nethack_keypad); write_setting_i(sesskey, "AltF4", cfg->alt_f4); write_setting_i(sesskey, "AltSpace", cfg->alt_space); write_setting_i(sesskey, "AltOnly", cfg->alt_only); write_setting_i(sesskey, "AltMetaBit", cfg->alt_metabit); write_setting_i(sesskey, "CtrlTabSwitch", cfg->ctrl_tab_switch); write_setting_i(sesskey, "ComposeKey", cfg->compose_key); write_setting_i(sesskey, "CtrlAltKeys", cfg->ctrlaltkeys); write_setting_i(sesskey, "RightAltKey", cfg->rightaltkey); write_setting_i(sesskey, "TelnetKey", cfg->telnet_keyboard); write_setting_i(sesskey, "TelnetRet", cfg->telnet_newline); write_setting_i(sesskey, "LocalEcho", cfg->localecho); write_setting_i(sesskey, "LocalEdit", cfg->localedit); write_setting_s(sesskey, "Answerback", cfg->answerback); write_setting_i(sesskey, "AlwaysOnTop", cfg->alwaysontop); write_setting_i(sesskey, "FullScreenOnAltEnter", cfg->fullscreenonaltenter); write_setting_i(sesskey, "HideMousePtr", cfg->hide_mouseptr); write_setting_i(sesskey, "SunkenEdge", cfg->sunken_edge); write_setting_filename(sesskey, "IconFile", cfg->iconfile); write_setting_i(sesskey, "WindowBorder", cfg->window_border); write_setting_i(sesskey, "CurType", cfg->cursor_type); write_setting_i(sesskey, "BlinkCur", cfg->blink_cur); write_setting_i(sesskey, "Beep", cfg->beep); write_setting_i(sesskey, "BeepInd", cfg->beep_ind); write_setting_filename(sesskey, "BellWaveFile", cfg->bell_wavefile); write_setting_i(sesskey, "BellOverload", cfg->bellovl); write_setting_i(sesskey, "BellOverloadN", cfg->bellovl_n); write_setting_i(sesskey, "BellOverloadT", cfg->bellovl_t #ifdef PUTTY_UNIX_H * 1000 #endif ); write_setting_i(sesskey, "BellOverloadS", cfg->bellovl_s #ifdef PUTTY_UNIX_H * 1000 #endif ); write_setting_i(sesskey, "ScrollbackLines", cfg->savelines); write_setting_i(sesskey, "DECOriginMode", cfg->dec_om); write_setting_i(sesskey, "AutoWrapMode", cfg->wrap_mode); write_setting_i(sesskey, "LFImpliesCR", cfg->lfhascr); write_setting_i(sesskey, "CRImpliesLF", cfg->crhaslf); write_setting_i(sesskey, "DisableArabicShaping", cfg->arabicshaping); write_setting_i(sesskey, "DisableBidi", cfg->bidi); write_setting_i(sesskey, "WinNameAlways", cfg->win_name_always); write_setting_s(sesskey, "WinTitle", cfg->wintitle); write_setting_i(sesskey, "TermWidth", cfg->width); write_setting_i(sesskey, "TermHeight", cfg->height); write_setting_i(sesskey, "TermX", cfg->x); write_setting_i(sesskey, "TermY", cfg->y); write_setting_fontspec(sesskey, "Font", cfg->font); write_setting_i(sesskey, "FontQuality", cfg->font_quality); write_setting_i(sesskey, "FontVTMode", cfg->vtmode); write_setting_i(sesskey, "UseSystemColours", cfg->system_colour); write_setting_i(sesskey, "TryPalette", cfg->try_palette); write_setting_i(sesskey, "ANSIColour", cfg->ansi_colour); write_setting_i(sesskey, "Xterm256Colour", cfg->xterm_256_colour); write_setting_i(sesskey, "BoldAsColour", cfg->bold_colour); for (i = 0; i < 24; i++) { char buf[20], buf2[30]; sprintf(buf, "Colour%d", i); sprintf(buf2, "%d,%d,%d", cfg->colours[i][0], cfg->colours[i][1], cfg->colours[i][2]); write_setting_s(sesskey, buf, buf2); } write_setting_i(sesskey, "RawCNP", cfg->rawcnp); write_setting_i(sesskey, "PasteRTF", cfg->rtf_paste); write_setting_s(sesskey, "IgnoreChars", cfg->ignore_chars); write_setting_i(sesskey, "MouseIsXterm", cfg->mouse_is_xterm); write_setting_i(sesskey, "RectSelect", cfg->rect_select); write_setting_i(sesskey, "MouseOverride", cfg->mouse_override); for (i = 0; i < 256; i += 32) { char buf[20], buf2[256]; int j; sprintf(buf, "Wordness%d", i); *buf2 = '\0'; for (j = i; j < i + 32; j++) { sprintf(buf2 + strlen(buf2), "%s%d", (*buf2 ? "," : ""), cfg->wordness[j]); } write_setting_s(sesskey, buf, buf2); } write_setting_s(sesskey, "LineCodePage", cfg->line_codepage); write_setting_i(sesskey, "CJKAmbigWide", cfg->cjk_ambig_wide); write_setting_i(sesskey, "UTF8Override", cfg->utf8_override); write_setting_s(sesskey, "Printer", cfg->printer); write_setting_i(sesskey, "CapsLockCyr", cfg->xlat_capslockcyr); write_setting_i(sesskey, "Use5Casis", cfg->use_5casis); write_setting_i(sesskey, "ScrollBar", cfg->scrollbar); write_setting_i(sesskey, "ScrollBarFullScreen", cfg->scrollbar_in_fullscreen); write_setting_i(sesskey, "ScrollOnKey", cfg->scroll_on_key); write_setting_i(sesskey, "ScrollOnDisp", cfg->scroll_on_disp); write_setting_i(sesskey, "EraseToScrollback", cfg->erase_to_scrollback); write_setting_i(sesskey, "LockSize", cfg->resize_action); write_setting_i(sesskey, "BCE", cfg->bce); write_setting_i(sesskey, "BlinkText", cfg->blinktext); write_setting_i(sesskey, "X11Forward", cfg->x11_forward); write_setting_s(sesskey, "X11Display", cfg->x11_display); write_setting_i(sesskey, "X11AuthType", cfg->x11_auth); write_setting_filename(sesskey, "X11AuthFile", cfg->xauthfile); write_setting_i(sesskey, "LocalPortAcceptAll", cfg->lport_acceptall); write_setting_i(sesskey, "RemotePortAcceptAll", cfg->rport_acceptall); wmap(sesskey, "PortForwardings", cfg->portfwd, lenof(cfg->portfwd)); write_setting_i(sesskey, "BugIgnore1", 2-cfg->sshbug_ignore1); write_setting_i(sesskey, "BugPlainPW1", 2-cfg->sshbug_plainpw1); write_setting_i(sesskey, "BugRSA1", 2-cfg->sshbug_rsa1); write_setting_i(sesskey, "BugIgnore2", 2-cfg->sshbug_ignore2); write_setting_i(sesskey, "BugHMAC2", 2-cfg->sshbug_hmac2); write_setting_i(sesskey, "BugDeriveKey2", 2-cfg->sshbug_derivekey2); write_setting_i(sesskey, "BugRSAPad2", 2-cfg->sshbug_rsapad2); write_setting_i(sesskey, "BugPKSessID2", 2-cfg->sshbug_pksessid2); write_setting_i(sesskey, "BugRekey2", 2-cfg->sshbug_rekey2); write_setting_i(sesskey, "BugMaxPkt2", 2-cfg->sshbug_maxpkt2); write_setting_i(sesskey, "StampUtmp", cfg->stamp_utmp); write_setting_i(sesskey, "LoginShell", cfg->login_shell); write_setting_i(sesskey, "ScrollbarOnLeft", cfg->scrollbar_on_left); write_setting_fontspec(sesskey, "BoldFont", cfg->boldfont); write_setting_fontspec(sesskey, "WideFont", cfg->widefont); write_setting_fontspec(sesskey, "WideBoldFont", cfg->wideboldfont); write_setting_i(sesskey, "ShadowBold", cfg->shadowbold); write_setting_i(sesskey, "ShadowBoldOffset", cfg->shadowboldoffset); write_setting_s(sesskey, "SerialLine", cfg->serline); write_setting_i(sesskey, "SerialSpeed", cfg->serspeed); write_setting_i(sesskey, "SerialDataBits", cfg->serdatabits); write_setting_i(sesskey, "SerialStopHalfbits", cfg->serstopbits); write_setting_i(sesskey, "SerialParity", cfg->serparity); write_setting_i(sesskey, "SerialFlowControl", cfg->serflow); write_setting_s(sesskey, "WindowClass", cfg->winclass); /* HACK: PuttyTray / Reconnect */ write_setting_i(sesskey, "WakeupReconnect", cfg->wakeup_reconnect); write_setting_i(sesskey, "FailureReconnect", cfg->failure_reconnect); /* Hyperlink */ write_setting_i(sesskey, "HyperlinkEnable", cfg->url_enable); write_setting_i(sesskey, "HyperlinkUnderline", cfg->url_underline); write_setting_i(sesskey, "HyperlinkUseCtrlClick", cfg->url_ctrl_click); /* Background */ write_setting_i(sesskey, "BackgroundWallpaper", cfg->bg_wallpaper); write_setting_i(sesskey, "BackgroundEffect", cfg->bg_effect); write_setting_filename(sesskey, "WallpaperFile", cfg->wp_file); write_setting_i(sesskey, "WallpaperPosition", cfg->wp_position); write_setting_i(sesskey, "WallpaperAlign", cfg->wp_align); write_setting_i(sesskey, "WallpaperVerticalAlign", cfg->wp_valign); write_setting_i(sesskey, "WallpaperMoving", cfg->wp_moving); /* Transparency */ for (i = 0; i < 4; i++) { char buf[16], buf2[16]; sprintf(buf, "Alpha%d", i); sprintf(buf2, "%d,%d", cfg->alphas_pc[i][0], cfg->alphas_pc[i][1]); write_setting_s(sesskey, buf, buf2); } }
int read_config(int reload) { FILE *config; int linenum = 0, retval = 1; char buf[1024], *s; int defconCount = 0; if (reload) { int i, n; /* Reset all the reloadable settings */ for (n = 0; n < lenof(directives); n++) { Directive *d = &directives[n]; for (i = 0; i < MAXPARAMS && d->params[i].type != PARAM_NONE; i++) { if (!(d->params[i].flags & PARAM_RELOAD)) continue; if (d->params[i].type == PARAM_SET || d->params[i].type == PARAM_INT || d->params[i].type == PARAM_POSINT || d->params[i].type == PARAM_TIME) { *(int *) d->params[i].ptr = 0; } else if (d->params[i].type == PARAM_STRING) { if (*(char **) d->params[i].ptr) free(*(char **) d->params[i].ptr); (*(char **) d->params[i].ptr) = NULL; } } } } config = fopen(SERVICES_CONF, "r"); if (!config) { #ifndef NOT_MAIN log_perror("Can't open " SERVICES_CONF); if (!nofork && isatty(2)) { #endif if (!reload) perror("Can't open " SERVICES_CONF); else alog("Can't open %s", SERVICES_CONF); #ifndef NOT_MAIN } #endif return 0; } while (fgets(buf, sizeof(buf), config)) { linenum++; if (*buf == '#' || *buf == '\r' || *buf == '\n') continue; if (!parse(buf, linenum, reload)) retval = 0; } fclose(config); if (!reload) { CHECK(RemoteServer); CHECK(ServerName); CHECK(ServerDesc); if (RemoteServer3) CHECK(RemoteServer2); if (LocalHost && RemoteServer) { if ((!stricmp(LocalHost, RemoteServer)) && LocalPort == RemotePort) { printf ("\n*** LocalAddress and RemoteServer are set to use the same IP address\n" "*** (%s) and port (%d). This would have resulted in errors.\n" "*** Change the LocalAddress to bind to another port.\n", RemoteServer, LocalPort); retval = 0; } } if (NickLen == 0) { alog("You have not defined the NickLen configuration directive. It is strongly"); alog("advised that you do configure this correctly in your services.conf"); NickLen = NICKMAX - 1; } else if ((NickLen < 1) || (NickLen >= NICKMAX)) { alog("NickLen has an invalid value; setting to %d", (NICKMAX - 1)); NickLen = NICKMAX - 1; } } CHECK(IRCDModule); CHECK(EncModule); CHECK(NetworkName); if (!reload) { CHEK2(temp_userhost, ServiceUser); CHEK2(s_NickServ, NickServName); CHEK2(s_ChanServ, ChanServName); CHEK2(s_MemoServ, MemoServName); CHEK2(s_HelpServ, HelpServName); CHEK2(s_OperServ, OperServName); CHEK2(s_GlobalNoticer, GlobalName); CHEK2(PIDFilename, PIDFile); } if (s_ChanServAlias) { if (!stricmp(s_ChanServ, s_ChanServAlias)) { printf ("\n*** ChanServ and ChanServ Alias are the same, this will cause errors\n"); retval = 0; } } if (s_NickServAlias) { if (!stricmp(s_NickServ, s_NickServAlias)) { printf ("\n*** NickServ and NickServ Alias are the same, this will cause errors\n"); retval = 0; } } if (s_OperServAlias) { if (!stricmp(s_OperServ, s_OperServAlias)) { printf ("\n*** OperServ and OperServ Alias are the same, this will cause errors\n"); retval = 0; } } if (s_MemoServAlias) { if (!stricmp(s_MemoServ, s_MemoServAlias)) { printf ("\n*** MemoServ and MemoServ Alias are the same, this will cause errors\n"); retval = 0; } } if (s_HelpServAlias) { if (!stricmp(s_HelpServ, s_HelpServAlias)) { printf ("\n*** HelpServ and HelpServ Alias are the same, this will cause errors\n"); retval = 0; } } if (s_GlobalNoticerAlias) { if (!stricmp(s_GlobalNoticer, s_GlobalNoticerAlias)) { printf ("\n*** GlobalNoticer and GlobalNoticer Alias are the same, this will cause errors\n"); retval = 0; } } CHEK2(MOTDFilename, MOTDFile); if (!reload) { CHEK2(NickDBName, NickServDB); CHEK2(ChanDBName, ChanServDB); CHEK2(OperDBName, OperServDB); CHEK2(NewsDBName, NewsDB); CHEK2(ExceptionDBName, ExceptionDB); } CHECK(UpdateTimeout); CHECK(ExpireTimeout); CHECK(ReadTimeout); CHECK(WarningTimeout); CHECK(TimeoutCheck); CHECK(NSAccessMax); CHEK2(temp_nsuserhost, NSEnforcerUser); CHECK(NSReleaseTimeout); CHECK(NSListMax); CHECK(CSAccessMax); CHECK(CSAutokickMax); CHECK(CSAutokickReason); CHECK(CSInhabit); CHECK(CSListMax); CHECK(ServicesRoot); CHECK(AutokillExpiry); CHECK(ChankillExpiry); CHECK(SGLineExpiry); CHECK(SQLineExpiry); CHECK(SZLineExpiry); if (!reload) { if (temp_userhost) { if (!(s = strchr(temp_userhost, '@'))) { error(0, "Missing `@' for ServiceUser"); } else { *s++ = 0; ServiceUser = temp_userhost; ServiceHost = s; } } } if (temp_nsuserhost) { if (!(s = strchr(temp_nsuserhost, '@'))) { NSEnforcerUser = temp_nsuserhost; NSEnforcerHost = ServiceHost; } else { *s++ = 0; NSEnforcerUser = temp_nsuserhost; NSEnforcerHost = s; } } if (!NSDefNone && !NSDefKill && !NSDefKillQuick && !NSDefSecure && !NSDefPrivate && !NSDefHideEmail && !NSDefHideUsermask && !NSDefHideQuit && !NSDefMemoSignon && !NSDefMemoReceive) { NSDefSecure = 1; NSDefMemoSignon = 1; NSDefMemoReceive = 1; } NSDefFlags = 0; if (!NSDefNone) { if (NSDefKill) NSDefFlags |= NI_KILLPROTECT; if (NSDefKillQuick) NSDefFlags |= NI_KILL_QUICK; if (NSDefSecure) NSDefFlags |= NI_SECURE; if (NSDefPrivate) NSDefFlags |= NI_PRIVATE; if (NSDefMsg) { if (!UsePrivmsg) alog("NSDefMsg can only be used when UsePrivmsg is set - unsetting NSDefMsg"); else NSDefFlags |= NI_MSG; } if (NSDefHideEmail) NSDefFlags |= NI_HIDE_EMAIL; if (NSDefHideUsermask) NSDefFlags |= NI_HIDE_MASK; if (NSDefHideQuit) NSDefFlags |= NI_HIDE_QUIT; if (NSDefMemoSignon) NSDefFlags |= NI_MEMO_SIGNON; if (NSDefMemoReceive) NSDefFlags |= NI_MEMO_RECEIVE; if (!NSDefAutoop) NSDefFlags |= NI_AUTOOP; } if (!ServicesRoot) { error(0, "You must define the 'ServicesRoot' configuration directive"); error(0, "in your services.conf file. This is a required setting that"); error(0, "defines the main Administrative nick(s) Anope will obey."); retval = 0; } CHECK(NSGuestNickPrefix); /* Add safety check */ if (NSGuestNickPrefix && (strlen(NSGuestNickPrefix) > 21)) { error(0, "Value of NSGuestNickPrefix must be between 1 and 21"); retval = 0; } CHECK(NSDefLanguage); if (NSDefLanguage) { NSDefLanguage--; if (NSDefLanguage < 0 || NSDefLanguage >= NUM_LANGS) { error(0, "Value of NSDefLanguage must be between 1 and %d", USED_LANGS); retval = 0; } } if (!NewsCount) { NewsCount = 3; } if (reload) { if ((NSDefLanguage = langlist[NSDefLanguage]) < 0) NSDefLanguage = DEF_LANGUAGE; } if (CSDefBantype < 0 || CSDefBantype > 3) { error(0, "Value of CSDefBantype must be between 0 and 3 included"); retval = 0; } if (!MysqlRetries || !MysqlRetryGap) { MysqlRetries = 5; MysqlRetryGap = 1; } else if (((MysqlRetries * MysqlRetryGap) > 60) || ((MysqlRetries * MysqlRetryGap) < 1)) { error(0, "MysqlRetries * MysqlRetryGap must be between 1 and 60, using standard values."); MysqlRetries = 5; MysqlRetryGap = 1; } if (!CSDefNone && !CSDefKeepTopic && !CSDefTopicLock && !CSDefPrivate && !CSDefRestricted && !CSDefSecure && !CSDefSecureOps && !CSDefSecureFounder && !CSDefSignKick && !CSDefSignKickLevel && !CSDefOpNotice) { CSDefKeepTopic = 1; CSDefSecure = 1; CSDefSecureFounder = 1; CSDefSignKick = 1; } CSDefFlags = 0; if (!CSDefNone) { if (CSDefKeepTopic) CSDefFlags |= CI_KEEPTOPIC; if (CSDefTopicLock) CSDefFlags |= CI_TOPICLOCK; if (CSDefPrivate) CSDefFlags |= CI_PRIVATE; if (CSDefRestricted) CSDefFlags |= CI_RESTRICTED; if (CSDefSecure) CSDefFlags |= CI_SECURE; if (CSDefSecureOps) CSDefFlags |= CI_SECUREOPS; if (CSDefSecureFounder) CSDefFlags |= CI_SECUREFOUNDER; if (CSDefSignKick) CSDefFlags |= CI_SIGNKICK; if (CSDefSignKickLevel) CSDefFlags |= CI_SIGNKICK_LEVEL; if (CSDefOpNotice) CSDefFlags |= CI_OPNOTICE; if (CSDefXOP) CSDefFlags |= CI_XOP; if (CSDefPeace) CSDefFlags |= CI_PEACE; } BSDefFlags = 0; if (BSDefDontKickOps) BSDefFlags |= BS_DONTKICKOPS; if (BSDefDontKickVoices) BSDefFlags |= BS_DONTKICKVOICES; if (BSDefGreet) BSDefFlags |= BS_GREET; if (BSDefFantasy) BSDefFlags |= BS_FANTASY; if (BSDefSymbiosis) BSDefFlags |= BS_SYMBIOSIS; /* Services Root building */ if (ServicesRoot && !reload) { /* Check to prevent segmentation fault if it's missing */ while( RootNumber ) free(ServicesRoots[--RootNumber]); s = strtok(ServicesRoot, " "); do { if (s) { RootNumber++; ServicesRoots = srealloc(ServicesRoots, sizeof(char *) * RootNumber); ServicesRoots[RootNumber - 1] = sstrdup(s); } } while ((s = strtok(NULL, " "))); } if (!RootNumber) { error(0, "No ServicesRoot defined"); retval = 0; } /* Ulines */ if (UlineServers) { while( NumUlines ) free(Ulines[--NumUlines]); s = strtok(UlineServers, " "); do { if (s) { NumUlines++; Ulines = srealloc(Ulines, sizeof(char *) * NumUlines); Ulines[NumUlines - 1] = sstrdup(s); } } while ((s = strtok(NULL, " "))); } /* Host Setters building... :P */ while( HostNumber ) free(HostSetters[--HostNumber]); Anope_Free(HostSetters); HostSetters = buildStringList(HostSetter, &HostNumber); /* Modules Autoload building... :P */ while( ModulesNumber ) free(ModulesAutoload[--ModulesNumber]); Anope_Free(ModulesAutoload); ModulesAutoload = buildStringList(Modules, &ModulesNumber); while( ModulesDelayedNumber ) free(ModulesDelayedAutoload[--ModulesDelayedNumber]); Anope_Free(ModulesDelayedAutoload); ModulesDelayedAutoload = buildStringList(ModulesDelayed, &ModulesDelayedNumber); while( HostServCoreNumber ) free(HostServCoreModules[--HostServCoreNumber]); Anope_Free(HostServCoreModules); HostServCoreModules = buildStringList(HostCoreModules, &HostServCoreNumber); while( MemoServCoreNumber ) free(MemoServCoreModules[--MemoServCoreNumber]); Anope_Free(MemoServCoreModules); MemoServCoreModules = buildStringList(MemoCoreModules, &MemoServCoreNumber); while( HelpServCoreNumber ) free(HelpServCoreModules[--HelpServCoreNumber]); Anope_Free(HelpServCoreModules); HelpServCoreModules = buildStringList(HelpCoreModules, &HelpServCoreNumber); while( BotServCoreNumber ) free(BotServCoreModules[--BotServCoreNumber]); Anope_Free(BotServCoreModules); BotServCoreModules = buildStringList(BotCoreModules, &BotServCoreNumber); while( OperServCoreNumber ) free(OperServCoreModules[--OperServCoreNumber]); Anope_Free(OperServCoreModules); OperServCoreModules = buildStringList(OperCoreModules, &OperServCoreNumber); while( ChanServCoreNumber ) free(ChanServCoreModules[--ChanServCoreNumber]); Anope_Free(ChanServCoreModules); ChanServCoreModules = buildStringList(ChanCoreModules, &ChanServCoreNumber); while( NickServCoreNumber ) free(NickServCoreModules[--NickServCoreNumber]); Anope_Free(NickServCoreModules); NickServCoreModules = buildStringList(NickCoreModules, &NickServCoreNumber); if (LimitSessions) { CHECK(DefSessionLimit); CHECK(MaxSessionLimit); CHECK(ExceptionExpiry); if (MaxSessionKill && !SessionAutoKillExpiry) SessionAutoKillExpiry = 30 * 60; /* 30 minutes */ } if (s_BotServ) { CHEK2(BotDBName, BotServDB); CHECK(BSBadWordsMax); CHECK(BSMinUsers); CHECK(BSKeepData); if (s_BotServAlias) { if (!stricmp(s_BotServ, s_BotServAlias)) { printf ("\n*** BotServ and BotServ Alias are the same, this will cause errors\n"); retval = 0; } } if (!BSFantasyCharacter) BSFantasyCharacter = sstrdup("!"); if (BSFantasyCharacter && (strlen(BSFantasyCharacter) > 1)) { printf ("*** BSFantasyCharacter is more than 1 character long. Only the first\n" "*** character ('%c') will be used. The others will be ignored.\n", *BSFantasyCharacter); } } if (s_HostServ) { CHEK2(s_HostServ, HostServName); CHEK2(HostDBName, HostServDB); if (s_HostServAlias) { if (!stricmp(s_HostServ, s_HostServAlias)) { printf ("\n*** HostServ and HostServ Alias are the same, this will cause errors\n"); retval = 0; } } } if (UseMail) { CHECK(SendMailPath); CHECK(SendFrom); } if (GlobalOnCycle) { if (!GlobalOnCycleMessage && !GlobalOnCycleUP) { alog("GlobalOnCycleMessage and GlobalOnCycleUP are not defined; disabling GlobalOnCycle"); GlobalOnCycle = 0; } } /* Check the user keys */ if ((UserKey1 == UserKey2) || (UserKey1 == UserKey3) || (UserKey3 == UserKey2)) alog("Every UserKey must be different. It's for YOUR safety! Remember that!"); /** * Check all DEFCON dependiencies... **/ if (DefConLevel) { CHECK(DefCon1); CHECK(DefCon2); CHECK(DefCon3); CHECK(DefCon4); DefCon5 = 0; /* ALWAYS have defcon 5 as normal operation */ /* Build DefCon's */ DefCon[0] = 0; DefCon[1] = DefCon1; DefCon[2] = DefCon2; DefCon[3] = DefCon3; DefCon[4] = DefCon4; DefCon[5] = DefCon5; for (defconCount = 1; defconCount <= 5; defconCount++) { /* Check any defcon needed settings */ if (DefCon[defconCount] & DEFCON_REDUCE_SESSION) { CHECK(DefConSessionLimit); } if (DefCon[defconCount] & DEFCON_AKILL_NEW_CLIENTS) { CHECK(DefConAKILL); CHECK(DefConAkillReason); } if (DefCon[defconCount] & DEFCON_FORCE_CHAN_MODES) { CHECK(DefConChanModes); } } if (GlobalOnDefconMore) CHECK(DefconMessage); } /** * If they try to enable any email registration option, * make sure they have everything else they need too... * * rob **/ if (NSEmailReg) { CHEK2(PreNickDBName, PreNickServDB); CHECK(NSEmailReg); CHECK(NSRExpire); CHECK(UseMail); CHECK(NSForceEmail); } else { Anope_Free(PreNickDBName); PreNickDBName = NULL; NSRExpire = 0; } if (!retval) { printf ("\n*** Support resources: Read through the services.conf self-contained \n*** documentation. Read the documentation files found in the 'docs' \n*** folder. Visit our portal located at http://www.anope.org/. Join \n*** our support channel on /server irc.anope.org channel #anope.\n\n"); } return retval; }
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* * The generator g = 2 (used for both group1 and group14). */ static const unsigned char G[] = { 2 }; static const struct ssh_kex ssh_diffiehellman_group1_sha1 = { "diffie-hellman-group1-sha1", "group1", KEXTYPE_DH, P1, G, lenof(P1), lenof(G), &ssh_sha1 }; static const struct ssh_kex *const group1_list[] = { &ssh_diffiehellman_group1_sha1 }; const struct ssh_kexes ssh_diffiehellman_group1 = { sizeof(group1_list) / sizeof(*group1_list), group1_list }; static const struct ssh_kex ssh_diffiehellman_group14_sha1 = { "diffie-hellman-group14-sha1", "group14", KEXTYPE_DH, P14, G, lenof(P14), lenof(G), &ssh_sha1 };
//************************************************************************* // Method: fillModuleListTH32 // Description: support function // //************************************************************************* bool StackWalker::fillModuleListTH32( ModuleList& modules, DWORD pid ) { // CreateToolhelp32Snapshot() typedef HANDLE (__stdcall *tCT32S)( DWORD dwFlags, DWORD th32ProcessID ); // Module32First() typedef BOOL (__stdcall *tM32F)( HANDLE hSnapshot, LPMODULEENTRY32 lpme ); // Module32Next() typedef BOOL (__stdcall *tM32N)( HANDLE hSnapshot, LPMODULEENTRY32 lpme ); // I think the DLL is called tlhelp32.dll on Win9X, so we try both const char *dllname[] = { "kernel32.dll", "tlhelp32.dll" }; HINSTANCE hToolhelp; tCT32S pCT32S; tM32F pM32F; tM32N pM32N; HANDLE hSnap; MODULEENTRY32 me = { sizeof me }; bool keepGoing; ModuleEntry e; int i; for ( i = 0; i < lenof( dllname ); ++ i ) { hToolhelp = LoadLibrary( dllname[i] ); if ( hToolhelp == 0 ) continue; pCT32S = (tCT32S) GetProcAddress( hToolhelp, "CreateToolhelp32Snapshot" ); pM32F = (tM32F) GetProcAddress( hToolhelp, "Module32First" ); pM32N = (tM32N) GetProcAddress( hToolhelp, "Module32Next" ); if ( pCT32S != 0 && pM32F != 0 && pM32N != 0 ) break; // found the functions! FreeLibrary( hToolhelp ); hToolhelp = 0; } if ( hToolhelp == 0 ) // nothing found? return false; hSnap = pCT32S( TH32CS_SNAPMODULE, pid ); if ( hSnap == (HANDLE) -1 ) return false; keepGoing = !!pM32F( hSnap, &me ); while ( keepGoing ) { // here, we have a filled-in MODULEENTRY32 //printf( "%08lXh %6lu %-15.15s %s\n", me.modBaseAddr, me.modBaseSize, me.szModule, me.szExePath ); e.imageName = me.szExePath; e.moduleName = me.szModule; e.baseAddress = (DWORD) me.modBaseAddr; e.size = me.modBaseSize; modules.push_back( e ); keepGoing = !!pM32N( hSnap, &me ); } CloseHandle( hSnap ); FreeLibrary( hToolhelp ); return modules.size() != 0; }
void DEBUGSTR( int level, LPTSTR szFormat, ... ) { static char tempfile[MAX_PATH]; static DWORD pid; TCHAR szBuffer[1024], szEscape[1024]; va_list pArgList; HANDLE mutex; DWORD wait; FILE* file; if ((log_level & 3) < level && !(level & 4 & log_level)) return; if (*tempfile == '\0') { _snprintf( tempfile, MAX_PATH, "%s\\ansicon.log", getenv( "TEMP" ) ); pid = GetCurrentProcessId(); } if (szFormat == NULL) { // Explicitly use 't', as _fmode might be binary. file = fopen( tempfile, (log_level & 8) ? "at" : "wt" ); if (file != NULL) { SYSTEMTIME now; GetLocalTime( &now ); fseek( file, 0, SEEK_END ); if (ftell( file ) != 0) putc( '\n', file ); fprintf( file, "ANSICON (" BITSA "-bit) v" PVERSA " log (%d) started " "%d-%.2d-%.2d %d:%.2d:%.2d\n", log_level, now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond ); fclose( file ); } return; } va_start( pArgList, szFormat ); _vsnwprintf( szBuffer, lenof(szBuffer), szFormat, pArgList ); va_end( pArgList ); szFormat = szBuffer; if (*szFormat == '\33') { BOOL first = TRUE; LPTSTR pos = szEscape; while (*++szFormat != '\0' && pos < szEscape + lenof(szEscape) - 4) { if (*szFormat < 32) { *pos++ = '\\'; switch (*szFormat) { case '\a': *pos++ = 'a'; break; case '\b': *pos++ = 'b'; break; case '\t': *pos++ = 't'; break; case '\r': *pos++ = 'r'; break; case '\n': *pos++ = 'n'; break; case 27 : *pos++ = 'e'; break; default: pos += _snwprintf( pos, 32, L"%.*o", (szFormat[1] >= '0' && szFormat[1] <= '7') ? 3 : 1, *szFormat ); } } else { if (*szFormat == '"') { if (first) first = FALSE; else if (szFormat[1] != '\0') *pos++ = '\\'; } *pos++ = *szFormat; } } *pos = '\0'; szFormat = szEscape; } mutex = CreateMutex( NULL, FALSE, L"ANSICON_debug_file" ); wait = WaitForSingleObject( mutex, 500 ); file = fopen( tempfile, "at" ); if (file != NULL) { fwprintf( file, L"%s (%lu): %s\n", prog, pid, szFormat ); fclose( file ); } if (wait == WAIT_OBJECT_0) ReleaseMutex( mutex ); CloseHandle( mutex ); }
//int _tmain( int argc, TCHAR* argv[] ) int main( void ) { STARTUPINFO si; PROCESS_INFORMATION pi; TCHAR* cmd; BOOL option; BOOL opt_m; BOOL installed; HMODULE ansi; int rc = 0; int argc; LPWSTR* argv = CommandLineToArgvW( GetCommandLine(), &argc ); if (argc > 1) { if (lstrcmp( argv[1], L"--help" ) == 0 || (argv[1][0] == '-' && (argv[1][1] == '?' || argv[1][1] == 'h')) || (argv[1][0] == '/' && argv[1][1] == '?')) { help(); return rc; } if (lstrcmp( argv[1], L"--version" ) == 0) { _putws( L"ANSICON (" BITS L"-bit) version " PVERS L" (" PDATE L")." ); return rc; } } #if (MYDEBUG > 1) DEBUGSTR( NULL ); // create a new file #endif option = (argc > 1 && argv[1][0] == '-'); if (option && (towlower( argv[1][1] ) == 'i' || towlower( argv[1][1] ) == 'u')) { process_autorun( argv[1][1] ); argv[1][1] = 'p'; } get_original_attr(); opt_m = FALSE; if (option && argv[1][1] == 'm') { WORD attr = 7; if (iswxdigit( argv[1][2] )) { attr = iswdigit( argv[1][2] ) ? argv[1][2] - '0' : (argv[1][2] | 0x20) - 'a' + 10; if (iswxdigit( argv[1][3])) { attr <<= 4; attr |= iswdigit( argv[1][3] ) ? argv[1][3] - '0' : (argv[1][3] | 0x20) - 'a' + 10; } } SetConsoleTextAttribute( hConOut, attr ); opt_m = TRUE; ++argv; --argc; option = (argc > 1 && argv[1][0] == '-'); } installed = (GetEnvironmentVariable( L"ANSICON", NULL, 0 ) != 0); if (option && argv[1][1] == 'p') { // If it's already installed, there's no need to do anything. if (installed) ; else if (GetParentProcessInfo( &pi )) { pi.hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId ); pi.hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, pi.dwThreadId ); SuspendThread( pi.hThread ); if (!Inject( &pi )) { _putws( L"ANSICON: parent process type is not supported." ); rc = 1; } ResumeThread( pi.hThread ); CloseHandle( pi.hThread ); CloseHandle( pi.hProcess ); } else { _putws( L"ANSICON: could not obtain the parent process." ); rc = 1; } } else { ansi = 0; if (!installed) { ansi = LoadLibrary( L"ANSI" BITS L".dll" ); if (!ansi) { fputws( L"ANSICON: failed to load ANSI" BITS L".dll.\n", stderr ); rc = 1; } } if (option && (argv[1][1] == 't' || argv[1][1] == 'T')) { BOOL title = (argv[1][1] == 'T'); if (argc == 2) { argv[2] = L"-"; ++argc; } for (; argc > 2; ++argv, --argc) { if (title) wprintf( L"==> %s <==\n", argv[2] ); display( argv[2], title ); if (title) putwchar( '\n' ); } } else { // Retrieve the original command line, skipping our name and the option. cmd = skip_spaces( skip_arg( skip_spaces( GetCommandLine() ) ) ); if (opt_m) cmd = skip_spaces( skip_arg( cmd ) ); if (cmd[0] == '-' && (cmd[1] == 'e' || cmd[1] == 'E')) { fputws( cmd + 3, stdout ); if (cmd[1] == 'e') putwchar( '\n' ); } else if (!_isatty( 0 ) && *cmd == '\0') { display( L"-", FALSE ); } else { if (*cmd == '\0') { cmd = _wgetenv( L"ComSpec" ); if (cmd == NULL) cmd = L"cmd"; } ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); if (CreateProcess( NULL, cmd, NULL,NULL, TRUE, 0, NULL,NULL, &si, &pi )) { BOOL console = FALSE; TCHAR name[MAX_PATH]; DWORD rc; CoInitialize( NULL ); do { // When I first tried doing this, it took a little while to // succeed. Testing again shows it works immediately - perhaps the // CoInitialize introduces enough of a delay. Still, play it safe // and keep trying. And if you're wondering why I do it at all, // ProcessType may detect GUI, even for a console process. That's // fine after injection (including -p), but not here. We *need* to // suspend our own execution whilst running the child, otherwise // bad things happen (besides which, I want to restore the original // attributes when the child exits). if (GetModuleFileNameEx( pi.hProcess, NULL, name, lenof(name) )) { DWORD_PTR info; info = SHGetFileInfo( name, 0, NULL, 0, SHGFI_EXETYPE ); if (info == 0x00004550) // console PE console = TRUE; DEBUGSTR( L"%s", name ); DEBUGSTR( L" %s (%p)", (console) ? L"Console" : L"Not console", info ); break; } Sleep( 10 ); } while (GetExitCodeProcess( pi.hProcess, &rc ) && rc == STILL_ACTIVE); CoUninitialize(); if (console) { SetConsoleCtrlHandler( (PHANDLER_ROUTINE)CtrlHandler, TRUE ); WaitForSingleObject( pi.hProcess, INFINITE ); } CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); } else { *skip_arg( cmd ) = '\0'; wprintf( L"ANSICON: '%s' could not be executed.\n", cmd ); rc = 1; } } } if (ansi) FreeLibrary( ansi ); } set_original_attr(); return rc; }
int main(int argc, char **argv) { int i, j; if (argc > 1) { /* * Generation of tests. * * Given `-splat <args>', we print out a C-style * representation of each argument (in the form "a", "b", * NULL), backslash-escaping each backslash and double * quote. * * Given `-split <string>', we first doctor `string' by * turning forward slashes into backslashes, single quotes * into double quotes and underscores into spaces; and then * we feed the resulting string to ourself with `-splat'. * * Given `-generate', we concoct a variety of fun test * cases, encode them in quote-safe form (mapping \, " and * space to /, ' and _ respectively) and feed each one to * `-split'. */ if (!strcmp(argv[1], "-splat")) { int i; char *p; for (i = 2; i < argc; i++) { putchar('"'); for (p = argv[i]; *p; p++) { if (*p == '\\' || *p == '"') putchar('\\'); putchar(*p); } printf("\", "); } printf("NULL"); return 0; } if (!strcmp(argv[1], "-split") && argc > 2) { char *str = malloc(20 + strlen(argv[0]) + strlen(argv[2])); char *p, *q; q = str + sprintf(str, "%s -splat ", argv[0]); printf(" {\""); for (p = argv[2]; *p; p++, q++) { switch (*p) { case '/': printf("\\\\"); *q = '\\'; break; case '\'': printf("\\\""); *q = '"'; break; case '_': printf(" "); *q = ' '; break; default: putchar(*p); *q = *p; break; } } *p = '\0'; printf("\", {"); fflush(stdout); system(str); printf("}},\n"); return 0; } if (!strcmp(argv[1], "-generate")) { char *teststr, *p; int i, initialquote, backslashes, quotes; teststr = malloc(200 + strlen(argv[0])); for (initialquote = 0; initialquote <= 1; initialquote++) { for (backslashes = 0; backslashes < 5; backslashes++) { for (quotes = 0; quotes < 9; quotes++) { p = teststr + sprintf(teststr, "%s -split ", argv[0]); if (initialquote) *p++ = '\''; *p++ = 'a'; for (i = 0; i < backslashes; i++) *p++ = '/'; for (i = 0; i < quotes; i++) *p++ = '\''; *p++ = 'b'; *p++ = '_'; *p++ = 'c'; *p++ = '\''; *p++ = '_'; *p++ = 'd'; *p = '\0'; system(teststr); } } } return 0; } fprintf(stderr, "unrecognised option: \"%s\"\n", argv[1]); return 1; } /* * If we get here, we were invoked with no arguments, so just * run the tests. */ for (i = 0; i < lenof(argv_tests); i++) { int ac; char **av; split_into_argv(argv_tests[i].cmdline, &ac, &av); for (j = 0; j < ac && argv_tests[i].argv[j]; j++) { if (strcmp(av[j], argv_tests[i].argv[j])) { printf("failed test %d (|%s|) arg %d: |%s| should be |%s|\n", i, argv_tests[i].cmdline, j, av[j], argv_tests[i].argv[j]); } #ifdef VERBOSE else { printf("test %d (|%s|) arg %d: |%s| == |%s|\n", i, argv_tests[i].cmdline, j, av[j], argv_tests[i].argv[j]); } #endif } if (j < ac) printf("failed test %d (|%s|): %d args returned, should be %d\n", i, argv_tests[i].cmdline, ac, j); if (argv_tests[i].argv[j]) printf("failed test %d (|%s|): %d args returned, should be more\n", i, argv_tests[i].cmdline, ac); } return 0; }
/* * This function is a wrapper on modpow(). It has the same effect * as modpow(), but employs RSA blinding to protect against timing * attacks. */ static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key) { Bignum random, random_encrypted, random_inverse; Bignum input_blinded, ret_blinded; Bignum ret; SHA512_State ss; unsigned char digest512[64]; int digestused = lenof(digest512); int hashseq = 0; /* * Start by inventing a random number chosen uniformly from the * range 2..modulus-1. (We do this by preparing a random number * of the right length and retrying if it's greater than the * modulus, to prevent any potential Bleichenbacher-like * attacks making use of the uneven distribution within the * range that would arise from just reducing our number mod n. * There are timing implications to the potential retries, of * course, but all they tell you is the modulus, which you * already knew.) * * To preserve determinism and avoid Pageant needing to share * the random number pool, we actually generate this `random' * number by hashing stuff with the private key. */ while (1) { int bits, byte, bitsleft, v; random = copybn(key->modulus); /* * Find the topmost set bit. (This function will return its * index plus one.) Then we'll set all bits from that one * downwards randomly. */ bits = bignum_bitcount(random); byte = 0; bitsleft = 0; while (bits--) { if (bitsleft <= 0) { bitsleft = 8; /* * Conceptually the following few lines are equivalent to * byte = random_byte(); */ if (digestused >= lenof(digest512)) { unsigned char seqbuf[4]; PUT_32BIT(seqbuf, hashseq); pSHA512_Init(&ss); SHA512_Bytes(&ss, "RSA deterministic blinding", 26); SHA512_Bytes(&ss, seqbuf, sizeof(seqbuf)); sha512_mpint(&ss, key->private_exponent); pSHA512_Final(&ss, digest512); hashseq++; /* * Now hash that digest plus the signature * input. */ pSHA512_Init(&ss); SHA512_Bytes(&ss, digest512, sizeof(digest512)); sha512_mpint(&ss, input); pSHA512_Final(&ss, digest512); digestused = 0; } byte = digest512[digestused++]; } v = byte & 1; byte >>= 1; bitsleft--; bignum_set_bit(random, bits, v); } /* * Now check that this number is strictly greater than * zero, and strictly less than modulus. */ if (bignum_cmp(random, Zero) <= 0 || bignum_cmp(random, key->modulus) >= 0) { freebn(random); continue; } else { break; } } /* * RSA blinding relies on the fact that (xy)^d mod n is equal * to (x^d mod n) * (y^d mod n) mod n. We invent a random pair * y and y^d; then we multiply x by y, raise to the power d mod * n as usual, and divide by y^d to recover x^d. Thus an * attacker can't correlate the timing of the modpow with the * input, because they don't know anything about the number * that was input to the actual modpow. * * The clever bit is that we don't have to do a huge modpow to * get y and y^d; we will use the number we just invented as * _y^d_, and use the _public_ exponent to compute (y^d)^e = y * from it, which is much faster to do. */ random_encrypted = modpow(random, key->exponent, key->modulus); random_inverse = modinv(random, key->modulus); input_blinded = modmul(input, random_encrypted, key->modulus); ret_blinded = modpow(input_blinded, key->private_exponent, key->modulus); ret = modmul(ret_blinded, random_inverse, key->modulus); freebn(ret_blinded); freebn(input_blinded); freebn(random_inverse); freebn(random_encrypted); freebn(random); return ret; }
int asn1_load_mscat(fmap_t *map, struct cl_engine *engine) { struct cli_asn1 c; unsigned int size; struct cli_matcher *db; int i; if(asn1_parse_mscat(map, 0, map->len, &engine->cmgr, 0, &c.next, &size, engine)) return 1; if(asn1_expect_objtype(map, c.next, &size, &c, 0x30)) return 1; if(asn1_expect_obj(map, &c.content, &c.size, 0x06, lenof(OID_szOID_CATALOG_LIST), OID_szOID_CATALOG_LIST)) return 1; if(c.size) { cli_dbgmsg("asn1_load_mscat: found extra data in szOID_CATALOG_LIST content\n"); return 1; } if(asn1_expect_objtype(map, c.next, &size, &c, 0x4)) /* List ID */ return 1; if(asn1_expect_objtype(map, c.next, &size, &c, 0x17)) /* Effective date - WTF?! */ return 1; if(asn1_expect_algo(map, &c.next, &size, lenof(OID_szOID_CATALOG_LIST_MEMBER), OID_szOID_CATALOG_LIST_MEMBER)) /* szOID_CATALOG_LIST_MEMBER */ return 1; if(asn1_expect_objtype(map, c.next, &size, &c, 0x30)) /* hashes here */ return 1; /* [0] is next but we don't care as it's really descriptives stuff */ size = c.size; c.next = c.content; while(size) { struct cli_asn1 tag; if(asn1_expect_objtype(map, c.next, &size, &c, 0x30)) return 1; if(asn1_expect_objtype(map, c.content, &c.size, &tag, 0x04)) /* TAG NAME */ return 1; if(asn1_expect_objtype(map, tag.next, &c.size, &tag, 0x31)) /* set */ return 1; if(c.size) { cli_dbgmsg("asn1_load_mscat: found extra data in tag\n"); return 1; } while(tag.size) { struct cli_asn1 tagval1, tagval2, tagval3; int hashtype; if(asn1_expect_objtype(map, tag.content, &tag.size, &tagval1, 0x30)) return 1; tag.content = tagval1.next; if(asn1_expect_objtype(map, tagval1.content, &tagval1.size, &tagval2, 0x06)) return 1; if(tagval2.size != lenof(OID_SPC_INDIRECT_DATA_OBJID)) continue; if(!fmap_need_ptr_once(map, tagval2.content, lenof(OID_SPC_INDIRECT_DATA_OBJID))) { cli_dbgmsg("asn1_load_mscat: cannot read SPC_INDIRECT_DATA\n"); return 1; } if(memcmp(tagval2.content, OID_SPC_INDIRECT_DATA_OBJID, lenof(OID_SPC_INDIRECT_DATA_OBJID))) continue; /* stuff like CAT_NAMEVALUE_OBJID(1.3.6.1.4.1.311.12.2.1) and CAT_MEMBERINFO_OBJID(.2).. */ if(asn1_expect_objtype(map, tagval2.next, &tagval1.size, &tagval2, 0x31)) return 1; if(tagval1.size) { cli_dbgmsg("asn1_load_mscat: found extra data in tag value\n"); return 1; } if(asn1_expect_objtype(map, tagval2.content, &tagval2.size, &tagval1, 0x30)) return 1; if(tagval2.size) { cli_dbgmsg("asn1_load_mscat: found extra data in SPC_INDIRECT_DATA_OBJID tag\n"); return 1; } if(asn1_expect_objtype(map, tagval1.content, &tagval1.size, &tagval2, 0x30)) return 1; if(asn1_expect_objtype(map, tagval2.content, &tagval2.size, &tagval3, 0x06)) /* shall have an obj 1.3.6.1.4.1.311.2.1.15 or 1.3.6.1.4.1.311.2.1.25 inside */ return 1; if(tagval3.size != lenof(OID_SPC_PE_IMAGE_DATA_OBJID)) { /* lenof(OID_SPC_PE_IMAGE_DATA_OBJID) = lenof(OID_SPC_CAB_DATA_OBJID) = 10*/ cli_dbgmsg("asn1_load_mscat: bad hash type size\n"); return 1; } if(!fmap_need_ptr_once(map, tagval3.content, lenof(OID_SPC_PE_IMAGE_DATA_OBJID))) { cli_dbgmsg("asn1_load_mscat: cannot read hash type\n"); return 1; } if(!memcmp(tagval3.content, OID_SPC_PE_IMAGE_DATA_OBJID, lenof(OID_SPC_PE_IMAGE_DATA_OBJID))) hashtype = 2; else if(!memcmp(tagval3.content, OID_SPC_CAB_DATA_OBJID, lenof(OID_SPC_CAB_DATA_OBJID))) hashtype = 1; else { cli_dbgmsg("asn1_load_mscat: unexpected hash type\n"); return 1; } if(asn1_expect_objtype(map, tagval2.next, &tagval1.size, &tagval2, 0x30)) return 1; if(tagval1.size) { cli_dbgmsg("asn1_load_mscat: found extra data after hash\n"); return 1; } if(asn1_expect_algo(map, &tagval2.content, &tagval2.size, lenof(OID_sha1), OID_sha1)) /* objid 1.3.14.3.2.26 - sha1 */ return 1; if(asn1_expect_objtype(map, tagval2.content, &tagval2.size, &tagval3, 0x04)) return 1; if(tagval2.size) { cli_dbgmsg("asn1_load_mscat: found extra data in hash\n"); return 1; } if(tagval3.size != SHA1_HASH_SIZE) { cli_dbgmsg("asn1_load_mscat: bad hash size %u\n", tagval3.size); return 1; } if(!fmap_need_ptr_once(map, tagval3.content, SHA1_HASH_SIZE)) { cli_dbgmsg("asn1_load_mscat: cannot read hash\n"); return 1; } if(cli_debug_flag) { char sha1[SHA1_HASH_SIZE*2+1]; for(i=0;i<SHA1_HASH_SIZE;i++) sprintf(&sha1[i*2], "%02x", ((uint8_t *)(tagval3.content))[i]); cli_dbgmsg("asn1_load_mscat: got hash %s (%s)\n", sha1, (hashtype == 2) ? "PE" : "CAB"); } if(!engine->hm_fp) { if(!(engine->hm_fp = mpool_calloc(engine->mempool, 1, sizeof(*db)))) { tag.size = 1;; return 1; } #ifdef USE_MPOOL engine->hm_fp->mempool = engine->mempool; #endif } if(hm_addhash_bin(engine->hm_fp, tagval3.content, CLI_HASH_SHA1, hashtype, NULL)) { cli_warnmsg("asn1_load_mscat: failed to add hash\n"); return 1; } } } return 0; }