5c93dde5814fddc96330bbdea7aa3f9ff374aedf angie Wed May 25 15:41:05 2016 -0700 In order to support userNames with leading/trailing spaces, CGI-encode the userName store in the cookie, and CGI-decode before comparing it to gbMembers.userName. refs #17396 note-15, note-17 diff --git src/hg/lib/wikiLink.c src/hg/lib/wikiLink.c index c05e473..d22d2d4 100644 --- src/hg/lib/wikiLink.c +++ src/hg/lib/wikiLink.c @@ -225,31 +225,31 @@ if (isNotEmpty(value)) // Set the cookie to value safef(cookieString, sizeof(cookieString), "%s=%s;%s path=/; expires="NO_EXPIRE_COOKIE_DATE, name, value, domain); else // Invalidate the cookie safef(cookieString, sizeof(cookieString), "%s=;%s path=/; expires="EXPIRED_COOKIE_DATE, name, domain); return slNameNew(cookieString); } static struct slName *loginUserNameCookieString(char *userName) /* Return a cookie string that sets userName cookie to userName if non-empty and * deletes/invalidates the cookie if empty/NULL. */ { -return newCookieString(loginUserNameCookie(), userName); +return newCookieString(loginUserNameCookie(), cgiEncodeFull(userName)); } static struct slName *loginIdKeyCookieString(uint idx, char *key) /* Return a cookie string that sets ID cookie to idKey if idKey is non-empty and * deletes/invalidates the cookie if empty/NULL. */ { char newVal[1024]; if (isNotEmpty(key)) safef(newVal, sizeof(newVal), "%u_%s", idx, key); else safef(newVal, sizeof(newVal), "%u", idx); return newCookieString(loginIdKeyCookie(), idx ? newVal : NULL); } static char *makeNewKey() @@ -336,58 +336,71 @@ static void remoteHostBypass() /* If a remote host was used for login, redirecting back to this server, then this server's * central database does not have the correct login token -- so we can't validate cookies. * Fall back on the old method of just accepting whatever cookies we get. Unfortunately * we'll have to take a guess at what those cookies are, although hg.conf can override. */ { char *wikiHost = cfgOption(CFG_WIKI_HOST); if (isEmpty(wikiHost) || sameString(wikiHost, "HTTPHOST") || sameString(wikiHost, hHttpHost())) return; alreadyAuthenticated = TRUE; cookieStrings = NULL; char *cookiePrefix = getRemoteCookiePrefix(wikiHost); char *userName = getRemoteCookieVal(CFG_LOGIN_USER_NAME_COOKIE, cookiePrefix, "hgLoginUserName"); char *idKey = getRemoteCookieVal(CFG_LOGIN_IDKEY_COOKIE, cookiePrefix, "hgLoginToken"); authenticated = (isNotEmpty(userName) && isNotEmpty(idKey)); -remoteUserName = userName; +if (isNotEmpty(userName)) + { + remoteUserName = cloneString(userName); + cgiDecodeFull(remoteUserName, remoteUserName, strlen(remoteUserName)); + } // BEGIN TODO: remove in July 2016 if (! authenticated && wikiLinkEnabled()) { // Accept old wiki cookies for now char *wikiUserName = findCookieData(wikiLinkUserNameCookie()); char *wikiLoggedIn = findCookieData(wikiLinkLoggedInCookie()); if (isNotEmpty(wikiLoggedIn) && isNotEmpty(wikiUserName)) { authenticated = TRUE; remoteUserName = wikiUserName; } } // END TODO: remove in July 2016 } +static char *getLoginUserName() +/* Get the (CGI-decoded) value of the login userName cookie. */ +{ +char *userName = cloneString(findCookieData(loginUserNameCookie())); +if (isNotEmpty(userName)) + cgiDecodeFull(userName, userName, strlen(userName)); +return userName; +} + struct slName *loginValidateCookies() /* Return possibly empty list of cookie strings for the caller to set. * If login cookies are obsolete but (formerly) valid, the results sets updated cookies. * If login cookies are present but invalid, the result deletes/expires the cookies. * Otherwise returns NULL (no change to cookies). */ { remoteHostBypass(); if (alreadyAuthenticated) return cookieStrings; alreadyAuthenticated = TRUE; authenticated = FALSE; -char *userName = findCookieData(loginUserNameCookie()); +char *userName = getLoginUserName(); // BEGIN TODO: remove in July 2016 // If we're using values from old wiki cookies, replace the cookies. boolean replaceOldCookies = FALSE; if (isEmpty(userName) && wikiLinkEnabled()) { userName = findCookieData(wikiLinkUserNameCookie()); if (isNotEmpty(userName)) replaceOldCookies = TRUE; } boolean deleteCookies = FALSE; // END TODO: remove in July 2016 char *cookieKey = NULL; uint cookieIdx = getCookieIdKey(&cookieKey, &replaceOldCookies); @@ -455,31 +468,31 @@ { char *wikiHost = cfgOption(CFG_WIKI_HOST); if (isEmpty(wikiHost) || sameString(wikiHost, "HTTPHOST")) wikiHost = hHttpHost(); return cloneString(wikiHost); } char *wikiLinkUserName() /* Return the user name specified in cookies from the browser, or NULL if * the user doesn't appear to be logged in. */ { if (loginSystemEnabled()) { if (! alreadyAuthenticated) errAbort("wikiLinkUserName: loginValidateCookies must be called first."); - char *userName = findCookieData(loginUserNameCookie()); + char *userName = getLoginUserName(); if (isEmpty(userName) && wikiLinkEnabled()) // TODO: remove in July 2016 userName = findCookieData(wikiLinkUserNameCookie()); // TODO: remove in July 2016 if (isEmpty(userName) && isNotEmpty(remoteUserName)) userName = remoteUserName; if (authenticated) return cloneString(userName); } else if (wikiLinkEnabled()) { char *wikiUserName = findCookieData(wikiLinkUserNameCookie()); char *wikiLoggedIn = findCookieData(wikiLinkLoggedInCookie()); if (isNotEmpty(wikiLoggedIn) && isNotEmpty(wikiUserName)) return cloneString(wikiUserName); } else