<% /* $Revision$ $Id$ File: common.inc Description: Common code die vooraan elk bestand *wordt uitgevoerd* We proberen op allerlei manieren te achterhalen of de gebruiker bekend is. Zo niet dan doen we uiteindelijk een redirect naar login.asp Parameters: Voor het includen van dit bestand kun je nog wat globale variabelen zetten om het gedrag te beinvloeden. JSON_Result ==> Altijd JSON result (auto DOCTYPE_Disable) DOCTYPE_Disable ==> Geen DOCTYPE header (voor JSON-requests) LCL_Disable ==> Geen lcl's cachen ANONYMOUS_Allowed ==> Voorkom redirect naar login.asp als niet ingelogd FCLTEXPIRES ==> Zet expire tijd van pagina (anders -1) LOGIN_try ==> Alleen vanuit LoginTry.asp==>geen redirect naar LoginTry.asp DBUPGRADE ==> Alleen vanuit dbupgrade.asp==>geen redirect naar dbupgrade.asp Context: vanuit ELK asp bestand Note: Dus gebruik met mate Setting gaan in default.inc Functies gaan naar shared.inc */ Session("page_start") = (new Date()).getTime(); // kun je in AiAi logging terugvinden, interessant bij timeouts // Diverse andere variabelen zijn afhankelijk van rooturl en vooral customerId. Héél vroeg bepalen dus! var rooturl; var customerId; determineCustomerId(); // doet ook rooturl if (typeof JSON_Result == "undefined") JSON_Result = false; if (String(Request.ServerVariables("HTTP_ACCEPT")).toLowerCase() == "application/json") JSON_Result = true; // Als je het vraagt krijg je het ook if (JSON_Result) DOCTYPE_Disable = true; if (typeof DOCTYPE_Disable == "undefined") { Response.write(''); } /* global */ __Logging = Session("logging") || 0; // Voor robuustheid extra vroeg %> <% // Nu hebben we customerId. Wel doen voor m_connections.inc // zodat we tijdens database migratie ook offline kunnen zetten if (Request.QueryString("forceonline").Count > 0) Session("forceonline") = true; var FCLToffline = null; tryOffline(rooturl + "/cust/"); tryOffline(custpath + "/"); // deze is sterker var fso = Server.CreateObject("Scripting.FileSystemObject"); CreateFullPath(shared.tempFolder()); // Voor als die er nog niet is var db_schema = Application("SET_" + customerId + "_DB_SCHEMA"); var upgrade_script = Server.MapPath(rooturl+ '/appl/upg/') + '/DB{0}.sql'.format(db_schema); if (typeof DBUPGRADE == "undefined" && fso.FileExists(upgrade_script)) { Server.Execute(rooturl + "/appl/upg/dbupgrade.asp"); if (db_schema == Application("SET_" + customerId + "_DB_SCHEMA")) { var txt = "Fatal Facilitor error session {0} at {1}".format(Session.SessionID, toISODateTimeString(new Date())); txt += "
Database schema number 'DB{0}' was not updated properly by {1}".format(db_schema, upgrade_script); txt += "
Please contact Facilitor support"; txt += "
Unsupported: Temporarily remove {0}".format(upgrade_script); if (Application("otap_environment") == "O") { txt += ("
Or: clear FAC_VERSION_UPGRADING"); txt += ("
Or: set FAC_VERSION_SCHEMA to value found at end of {0}".format(upgrade_script)); } shared.simpel_page(txt); } } %> <% // NLS_LANG moet altijd op de webserver op WE8MSWIN1252 Response.Codepage = 1252; Response.Charset = 'windows-1252'; if (JSON_Result) Response.ContentType = "application/json"; if (Request.QueryString("api2").Count == 1 && Request.QueryString("mode") == "attachment") { Response.CacheControl = "max-age=604800"; // 1 week voor api2 bijlagen } else { Response.Expires = this.FCLTEXPIRES||-1; // Do not cache our ASP files if (!this.FCLTEXPIRES) Response.CacheControl = "no-cache, no-store"; if (typeof NO_ADDHEADER == "undefined") Response.AddHeader ("X-Content-Type-Options", "nosniff"); } settings.loadSET(); device.init(); var overrule_lcl = {}; var overrule_setting = []; function tryOverrule(path) { var fso = Server.CreateObject("Scripting.FileSystemObject"); var hookfile = Server.MapPath(path); if (fso.FileExists(hookfile)) { try { var hook = GetObject("script:"+hookfile); } catch (e) { // We zitten zéér ernstig in de problemen. Geen fancy AiAi gedoe Response.Write("Unable to read " + hookfile + "

"); Response.Write(e.description); Response.End; } // Deze mag de hookfile gebruiken hook.Overrule = { DEFAULT: function (naam, type, waarde) { overrule_setting.push({ naam: naam, type: type, waarde: waarde }); // Voor fac_verify var v = Application("SET_DEFAULT_" + naam); if (typeof v == "undefined" || type != Application("SET_T_" + naam) || waarde != Application("SET_DEFAULT_" + naam)) { Application.Lock(); Application("SET_DEFAULT_" + naam) = waarde; Application("SET_T_" + naam) = type; // Is voor alle klanten gelijk Application.UnLock(); __SafeDoLog("Default for setting {0} ({1}) set to {2} by cust/custenv.wsc DEFAULT".format(naam, type, waarde), "#FF0000"); } }, SET: function (naam, waarde) { settings.overrule_setting(naam.toLowerCase(), waarde); }, LCL: function (naam, waarde) { overrule_lcl[naam] = waarde; }, APPLICATION: function (naam, waarde) { if (Application(naam) != waarde) { Application.Lock(); Application(naam) = waarde; Application.UnLock(); } } } // Deze mogen de hookfiles gebruiken // Moet je ze wel in de wsc opnemen bij de properties hook.Oracle = Oracle; hook.__Log = __Log; hook.__DoLog = __DoLog; hook.safe = safe; // Met onderstaande kun je zeer foute trucs uithalen // Gedacht scenario: bijvoorbeeld in een testomgeving bij bepaalde // requests (API's) gericht logging aanzetten zonder bestanden // te hoeven wijzigen. var aspdata = { Application: Application, Request: Request, Session: Session, Request: Request, Response: Response, Server: Server }; var realuser = Session("fclt_realuser"); // De Windows user, niet noodzakelijkerwijs de FACILITOR user if (realuser) { aspdata.Username = realuser.split("\\").pop(); if (realuser.split("\\").length > 1) aspdata.Userdomain = realuser.split("\\")[0]; } hook.custenv(aspdata); hook = null; // zorg dat de GC het object kan opruimen. } } // Optionele overrules in cust/custenv.wsc en cust/XXXX/custenv.inc tryOverrule(rooturl + "/cust/custenv.wsc"); tryOverrule(custpath + "/custenv.wsc"); // deze is sterker // Plaats een offline.html bestandje in /cust/ of /cust/XXXX en de site gaat offline // Door url uit te breiden met ?forceonline=1 kun je toch naar binnen // Wat met API's? function tryOffline(path) { var fso = Server.CreateObject("Scripting.FileSystemObject"); var offlinefile = Server.MapPath(path + "offline.html"); var forceonlinefile = Server.MapPath(custpath + "/forceonline.txt"); if (fso.FileExists(offlinefile) && !fso.FileExists(forceonlinefile)) { Response.AddHeader("FCLT-Offline","offline"); /* global */ FCLToffline = offlinefile; if (typeof Session("forceonline") != "undefined") return; // Geen Response.Redirect. Dan kan de gebruiker geen F5 drukken om weer verbinding te krijgen na een tijdje var ftekst = fso.OpenTextFile(offlinefile); var tekst = ftekst.ReadAll(); ftekst.Close(); if (JSON_Result || getQParam("API2","")) // Bij API2 is onze JSON_Result vaak nog niet gezet { Response.Status = "503 Service Unavailable"; // Windows 2012 stuurt de volgende body doorgaans niet meer! // JSON.stringfy hebben we (nog!) niet gegarandeerd dus simpel houden Response.Write(tekst); Response.End; } else { shared.simpel_page(tekst); } } } // ip-restrictie controle var ips = S("sys_ip_restrict"); if (ips) { var ip = String(Request.ServerVariables("REMOTE_HOST")); var ips_intern = S("sys_ip_restrict_internal"); if (!new RegExp(ips.replace(/\./ig, "\\."), "ig").test(ip) && !(ips_intern && new RegExp(ips_intern.replace(/\./ig, "\\."), "ig").test(ip))) { Response.write ("Forbidden: IP address of the client has been rejected." ); // Doet IIS bij echte restrictie Response.Status = "403.6"; Response.end; } } if (S("hiresTimer")) { try // Dit is de allereerste code die ontdekt dat de DLL niet is geladen. Daarom nette foutmelding { hiresTimer = new ActiveXObject("SLNKDWF.About"); } catch(e) { abort_with_warning("SLNKDWFx64.DLL not properly installed.\n{0}".format(e.description)); } } if (S("auto_https") && Request.ServerVariables("SERVER_PORT") != "443") { Response.Redirect("https://" + Request.ServerVariables("SERVER_NAME") + rooturl + "?" + Request.ServerVariables("QUERY_STRING")); Response.End; } else { // 0 wordt ook ondersteund om het actief uit te schakelen if (typeof NO_ADDHEADER == "undefined" && S("hsts_maxage") >= 0 && Request.ServerVariables("SERVER_PORT") != "80") Response.AddHeader("Strict-Transport-Security", "max-age=" + S("hsts_maxage")); // Geen includeSubDomains, dat nekt http://facilitor.nl } // Merk op: door onze Server.Transfer's met API's of inloggen zie je in Fiddler wel // eens dat X-Frame-Options twee keer in de header komt. Slordig maar acceptabel. if (typeof NO_ADDHEADER == "undefined" && !S("allow_framed_facilitor")) Response.AddHeader ("X-Frame-Options", "sameorigin"); // voorkom ClickJacking if (typeof NO_ADDHEADER == "undefined" && S("csp_header") && S("csp_header") != "X") { if (this.CSP_EXTRADATA) // sta openstreemap tiles toe var csp_header = S("csp_header").format(S("csp_header_extradata")); else var csp_header = S("csp_header").format(""); Response.AddHeader("Content-Security-Policy", csp_header); } if (typeof NO_ADDHEADER == "undefined" && S("referrer_policy_header") && S("referrer_policy_header") != "X") Response.AddHeader("Referrer-Policy", S("referrer_policy_header")); protectHMAC.getProtectSecret(); // forceer eerste keer per dag var fixcookie = String(Request.Cookies("ASPFIXATION")); if (fixcookie) { var fixCustid = fixcookie.substr(0, customerId.length); if ( fixCustid != customerId) { // reset ingelogde user, customer wissel? Session("user_key")=user_key=-1; } } // Zie login.inc: ga ASP Session Fixation tegen. if (typeof Session("ASPFIXATION") != "undefined") { var fixcookie = Request.Cookies("ASPFIXATION"); if (Session("ASPFIXATION") != fixcookie) { // Simuleer logoff var ident = "&ident=" + customerId + "\\" + Session("user_key"); if (Session("login_date")) { ident += "&login_date=" + toISODateTimeString(new Date(Session("login_date"))) } Session("user_key")=user_key=-1; // geen remove hier, anders grijpt SSO direct weer in setASPFIXATION(); // zet nieuwe cookie Response.Redirect(rooturl + "/appl/shared/expired.asp?aspfixation=1" + ident); // ident zodat we wel weten *wie* dit overkomt } } else setASPFIXATION(); // eerste keer if (S("sys_ip_lockmode") > 0) { var ip = String(Request.ServerVariables("REMOTE_ADDR")); // We zijn relatief flexibel: de laatste 16 bit wijzigen staan we toe // Deze bescherming tegen session hijacking is dus maar heel beperkt if (IP.isIPv4(ip) && Session("last_ip") && Session("last_ip") != ip && !IP.inSubnet(Session("last_ip"), ip + "/16")) { var agent = String(Request.ServerVariables("HTTP_USER_AGENT")); shared.auditfail(L("lcl_autfai_ipchange").format(Session("last_ip"), ip, Session("userident"), agent), "#0ff"); // Simuleer logoff Session.Contents.Remove("last_ip"); Session("user_key")=user_key=-1; // geen remove hier, anders grijpt SSO direct weer in } } // Zijn we bekend? Zo niet dan naar login.asp om dat uit te zoeken var user_key = Session("user_key") || -1; var user_allowed = Session("locked_user_allowed") || []; if (user_key < 0 && typeof LOCKED_USER_OK != "undefined" && user_allowed.length) // Is de huidige pagina geschikt voor locked users? { for (var i = 0; i < user_allowed.length; i++) { if (LOCKED_USER_OK === true || (user_allowed[i].xmlnode == LOCKED_USER_OK.xmlnode && user_allowed[i].key == LOCKED_USER_OK.key)) { var user_key = user_allowed[i].locked_user_key; Session("user_lang") = "NL"; Session("time_zone") = "Europe/Amsterdam" break; } } } var user; // wordt bij geldige user gevuld met new Perslid if ((user_key < 0 || getQParamInt("jwtforce", 0) == 1) && typeof LOGIN_try == "undefined") { Server.Execute(rooturl + "/appl/aut/loginTry.asp"); // Laat die het eens proberen op te lossen if (Session("user_key") > 0) { __Logging = Session("logging") || 0; // kan gezet geraakt zijn in loginTry.asp als prs_perslid_loglevel user_key = Session("user_key"); } } if (user_key < 0 && typeof ANONYMOUS_Allowed == "undefined") { var method = String(Request.ServerVariables("REQUEST_METHOD")); if (method == "HEAD" || method == "OPTIONS" || method == "PROPFIND") { // Een HEAD zonder cookies is waarschijnlijk afkomstig van Excel // met agent 'Microsoft+Office+Existence+Discovery' // Door de '405' heeft hij hopelijk door dat we echt geen WEBDAV doen Response.Status = "405 Method not allowed"; Response.End; } if (JSON_Result) // Login scherm werkt toch niet { Response.Clear(); // JSON.stringfy hebben we (nog!) niet gegarandeerd dus maar poor-man stringify Response.Write('{"warning":"'+L("lcl_not_loggedin").replace(/\n/g,"\\n").replace(/\"/g,"\\\"") +'","success":false}'); Response.End; } if (getQParamInt("nosso", "0") == 1) // Weiger alle automatische varianten { Response.Status = "401 Unauthorized"; Response.End; } var url = Session("unauth_url") || S("login_url"); // unauth_url uit shorturl.asp if (url == 'appl/shared/login.asp') // even compatible blijven url = 'appl/aut/login.asp'; if (getQParam("sso", "") == "0") // forceer de default url = 'appl/aut/login.asp'; if (!url.match(/^http/)) var url = rooturl + "/" + url; // "appl/shared/login.asp"; var ret_page = ""; if (String(Request.ServerVariables("REQUEST_METHOD")) == "GET") { ret_page = String(Request.ServerVariables("SCRIPT_NAME")); ret_page = ret_page.replace(/\/default.asp$/i, "/"); } var qs = String(Request.ServerVariables("QUERY_STRING")); if ((qs && qs != 'fac_id=' + customerId) || (ret_page && ret_page != rooturl + "/")) { url = protectQS.create(url + "?querystring=" + Server.URLencode(qs) + "&ret_page=" + Server.URLencode(ret_page)); } Response.Redirect(url); } if (user_key > 0) { if (typeof REGISTERMENU_Disable == "undefined") { var from_menu_key = getQParamInt("from_menu_key", -1); if (from_menu_key > 0) { shared.registeraction("menu", {refkey: from_menu_key, daily: S("fac_gui_counter_menu_daily")}); } } var from_search_key = getQParamInt("from_search_key", -1); if (from_search_key > 0) { var url = String(Request.ServerVariables("SCRIPT_NAME")) + "?" + String(Request.ServerVariables("QUERY_STRING")); url = url.replace("&from_search_key=" + from_search_key, ""); // Dat hoeven we er niet in te hebben if (url.indexOf(rooturl) == 0) url = url.substr(rooturl.length + 1); shared.registeraction("searchchoice", { refkey: from_search_key, info: url }); } if (typeof NO_ADDHEADER == "undefined" && Request.Servervariables("HTTP_FCLT_VERSION").Count > 0) { // wordt opgepikt door FCLTAPI.DLL voor in de logging en daarna gestript. Niet in Fiddler dus Response.AddHeader ("FCLT_USERID", customerId + "\\" + String(user_key)); } Session.Contents.Remove("fallback_user_key"); // uit shorturl.asp. Ondertussen niet meer nodig Session.Contents.Remove("unauth_url"); // uit shorturl.asp. Ondertussen niet meer nodig /* global */ user = new Perslid(user_key); if (typeof NO_OTP_OK == "undefined" && typeof ANONYMOUS_Allowed == "undefined") { if (Session("must_set_otp") == 1) Response.Redirect(rooturl + "/appl/prs/prs_perslid_otp_new.asp?prs_key=" + user_key); } if (typeof EXPIRED_PASSWORD_OK == "undefined" && typeof ANONYMOUS_Allowed == "undefined") { if (Session("must_reset_password") == 1) { Response.Redirect(rooturl + "/appl/prs/pchange.asp?expired=1"); } if (user.credentials_changed()) { // login.inc is niet standaard included dus kan ik geen doLogoff() doen // Dit triggert echter de rest wel? Session.Contents.Remove("user_key"); } } if (Session("must_accept_terms") == 1 && typeof TERMS_CONDITIONS_OK == "undefined") { Response.Redirect(rooturl + "/appl/prs/terms.asp"); } CheckForLogging(Request.QueryString("LOGGING")); } else // zitten we in een bestand wat het user-object nooit benadert { // Wel een dummy user object aanmaken om de ergste AiAi's // op http://xxxx.facilitor.nl/api2/departments/ te voorkomen var user = { checkAutorisation: function () { Response.Status = "401 Unauthorized"; Response.End; } } user.has = user.checkAutorisation; } // Zorg dat dit de *allerlaatste* functie is die je op een asp pagina aanroept. // En/of plaats dit vlak voor een Response.End of een Response.Redirect function ASPPAGE_END() { if (__Logging > 0) { var now = new Date(); var start = new Date(Session("page_start")); var duration = now.getTime() - start.getTime(); // _sql_cnt en _sql_time worden in m_connections.inc bijgehouden var txt = "Page took {0} seconds ({1} sql={2}s, nonsql={3}s, log overhead={4}s)" .format(Math.round(duration / 10) / 100, _sql_cnt, Math.round(_sql_time / 10) / 100, Math.round((duration - _sql_time - _logger_time) / 10) / 100, Math.round(_logger_time / 10) / 100); __Log(txt); check_recordsets(); // laatste sluiten dump_recordsets(); } Oracle.RealConnection.Close(); } %>