080a160c7b9595d516c9c70e83689a09b60839d0 galt Mon Jun 3 12:16:53 2013 -0700 fix SQL Injection diff --git src/hg/hgSession/hgSession.c src/hg/hgSession/hgSession.c index ac7647f..c1d9ccb 100644 --- src/hg/hgSession/hgSession.c +++ src/hg/hgSession/hgSession.c @@ -272,31 +272,31 @@ void showExistingSessions(char *userName) /* Print out a table with buttons for sharing/unsharing/loading/deleting * previously saved sessions. */ { struct sqlConnection *conn = hConnectCentral(); struct sqlResult *sr = NULL; char **row = NULL; char query[512]; boolean foundAny = FALSE; char *encUserName = cgiEncodeFull(userName); boolean gotSettings = (sqlFieldIndex(conn, namedSessionTable, "settings") >= 0); printf("

My Sessions

\n"); printf("\n"); -safef(query, sizeof(query), "SELECT sessionName, shared, firstUse from %s " +sqlSafef(query, sizeof(query), "SELECT sessionName, shared, firstUse from %s " "WHERE userName = '%s' ORDER BY sessionName;", namedSessionTable, encUserName); sr = sqlGetResult(conn, query); printf("" "" ""); while ((row = sqlNextRow(sr)) != NULL) { char *encSessionName = row[0]; char *sessionName = cgiDecodeClone(encSessionName); char *link = NULL; boolean shared = atoi(row[1]); char *firstUse = row[2]; char buf[512]; printf("
session namecreated onuse this 
session 
delete this 
session 
share with 
others? 
link to
session
send to
mail
  "); @@ -613,57 +613,60 @@ boolean shareSession = cartBoolean(cart, hgsNewSessionShare); char *userName = getLinkUserName(); char *encUserName = cgiEncodeFull(userName); struct sqlConnection *conn = hConnectCentral(); if (sqlTableExists(conn, namedSessionTable)) { struct sqlResult *sr = NULL; struct dyString *dy = dyStringNew(16 * 1024); char **row; char *firstUse = "now()"; int useCount = INITIAL_USE_COUNT; char firstUseBuf[32]; /* If this session already existed, preserve its firstUse and useCount. */ - dyStringPrintf(dy, "SELECT firstUse, useCount FROM %s " + sqlDyStringPrintf(dy, "SELECT firstUse, useCount FROM %s " "WHERE userName = '%s' AND sessionName = '%s';", namedSessionTable, encUserName, encSessionName); sr = sqlGetResult(conn, dy->string); if ((row = sqlNextRow(sr)) != NULL) { safef(firstUseBuf, sizeof(firstUseBuf), "'%s'", row[0]); firstUse = firstUseBuf; useCount = atoi(row[1]) + 1; } sqlFreeResult(&sr); /* Remove pre-existing session (if any) before updating. */ dyStringClear(dy); - dyStringPrintf(dy, "DELETE FROM %s WHERE userName = '%s' AND " + sqlDyStringPrintf(dy, "DELETE FROM %s WHERE userName = '%s' AND " "sessionName = '%s';", namedSessionTable, encUserName, encSessionName); sqlUpdate(conn, dy->string); dyStringClear(dy); - dyStringPrintf(dy, "INSERT INTO %s ", namedSessionTable); + sqlDyStringPrintf(dy, "INSERT INTO %s ", namedSessionTable); dyStringAppend(dy, "(userName, sessionName, contents, shared, " "firstUse, lastUse, useCount) VALUES ("); dyStringPrintf(dy, "'%s', '%s', ", encUserName, encSessionName); dyStringAppend(dy, "'"); cleanHgSessionFromCart(cart); - cartEncodeState(cart, dy); + struct dyString *encoded = newDyString(4096); + cartEncodeState(cart, encoded); + sqlDyAppendEscaped(dy, encoded->string); + dyStringFree(&encoded); dyStringAppend(dy, "', "); dyStringPrintf(dy, "%d, ", (shareSession ? 1 : 0)); dyStringPrintf(dy, "%s, now(), %d);", firstUse, useCount); sqlUpdate(conn, dy->string); dyStringFree(&dy); /* Prevent modification of custom tracks just saved to namedSessionDb: */ cartCopyCustomTracks(cart); if (useCount > INITIAL_USE_COUNT) dyStringPrintf(dyMessage, "Overwrote the contents of session %s " "(that %s be shared with other users). " "%s %s", htmlEncode(sessionName), (shareSession ? "may" : "may not"), @@ -796,46 +799,46 @@ { struct dyString *dyMessage = dyStringNew(1024); struct hashEl *cartHelList = NULL, *hel = NULL; struct sqlConnection *conn = hConnectCentral(); char *userName = getLinkUserName(); char *encUserName = cgiEncodeFull(userName); boolean didSomething = FALSE; char query[512]; cartHelList = cartFindPrefix(cart, hgsSharePrefix); if (cartHelList != NULL) { struct hash *sharedHash = hashNew(0); char **row; struct sqlResult *sr; - safef(query, sizeof(query), + sqlSafef(query, sizeof(query), "select sessionName,shared from %s where userName = '%s'", namedSessionTable, encUserName); sr = sqlGetResult(conn, query); while ((row = sqlNextRow(sr)) != NULL) hashAddInt(sharedHash, row[0], atoi(row[1])); sqlFreeResult(&sr); for (hel = cartHelList; hel != NULL; hel = hel->next) { char *encSessionName = hel->name + strlen(hgsSharePrefix); char *sessionName = cgiDecodeClone(encSessionName); boolean alreadyShared = hashIntVal(sharedHash, encSessionName); boolean shared = cartUsualBoolean(cart, hel->name, TRUE); if (shared != alreadyShared) { - safef(query, sizeof(query), "UPDATE %s SET shared = %d " + sqlSafef(query, sizeof(query), "UPDATE %s SET shared = %d " "WHERE userName = '%s' AND sessionName = '%s';", namedSessionTable, shared, encUserName, encSessionName); sqlUpdate(conn, query); sessionTouchLastUse(conn, encUserName, encSessionName); dyStringPrintf(dyMessage, "Marked session %s as %s.
\n", htmlEncode(sessionName), (shared ? "shared" : "unshared")); didSomething = TRUE; } } hashFree(&sharedHash); } hel = cartFindPrefix(cart, hgsLoadPrefix); if (hel != NULL) @@ -847,31 +850,31 @@ dyStringPrintf(dyMessage, "Loaded settings from session %s. %s %s
\n", htmlEncode(sessionName), getSessionLink(encUserName, encSessionName), getSessionEmailLink(encUserName, encSessionName)); cartLoadUserSession(conn, userName, sessionName, cart, NULL, wildStr); checkForCustomTracks(dyMessage); didSomething = TRUE; } cartHelList = cartFindPrefix(cart, hgsDeletePrefix); for (hel = cartHelList; hel != NULL; hel = hel->next) { char *encSessionName = hel->name + strlen(hgsDeletePrefix); char *sessionName = cgiDecodeClone(encSessionName); - safef(query, sizeof(query), "DELETE FROM %s " + sqlSafef(query, sizeof(query), "DELETE FROM %s " "WHERE userName = '%s' AND sessionName = '%s';", namedSessionTable, encUserName, encSessionName); sqlUpdate(conn, query); dyStringPrintf(dyMessage, "Deleted session %s.
\n", htmlEncode(sessionName)); didSomething = TRUE; } hDisconnectCentral(&conn); if (didSomething) return(dyStringCannibalize(&dyMessage)); else { dyStringFree(&dyMessage); @@ -1002,35 +1005,35 @@ char *doSessionDetail(char *sessionName) /* Show details about a particular session. */ { struct dyString *dyMessage = dyStringNew(4096); char *encSessionName = cgiEncodeFull(sessionName); char *userName = getLinkUserName(); char *encUserName = cgiEncodeFull(userName); struct sqlConnection *conn = hConnectCentral(); struct sqlResult *sr = NULL; char **row = NULL; char query[512]; webPushErrHandlersCart(cart); boolean gotSettings = (sqlFieldIndex(conn, namedSessionTable, "settings") >= 0); if (gotSettings) - safef(query, sizeof(query), "SELECT shared, firstUse, settings from %s " + sqlSafef(query, sizeof(query), "SELECT shared, firstUse, settings from %s " "WHERE userName = '%s' AND sessionName = '%s'", namedSessionTable, encUserName, encSessionName); else - safef(query, sizeof(query), "SELECT shared, firstUse from %s " + sqlSafef(query, sizeof(query), "SELECT shared, firstUse from %s " "WHERE userName = '%s' AND sessionName = '%s'", namedSessionTable, encUserName, encSessionName); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { boolean shared = atoi(row[0]); char *firstUse = row[1]; char *settings = NULL; if (gotSettings) settings = row[2]; char *description = getSetting(settings, "description"); if (description == NULL) description = ""; dyStringPrintf(dyMessage, "Session Details Help

\n"); @@ -1108,119 +1111,116 @@ webPushErrHandlersCart(cart); char *sessionName = oldSessionName; char *encSessionName = cgiEncodeFull(sessionName); char *encOldSessionName = encSessionName; char *userName = getLinkUserName(); char *encUserName = cgiEncodeFull(userName); struct sqlConnection *conn = hConnectCentral(); struct sqlResult *sr = NULL; char **row = NULL; char query[512]; boolean shared = TRUE; char *settings = NULL; boolean gotSettings = (sqlFieldIndex(conn, namedSessionTable, "settings") >= 0); if (gotSettings) - safef(query, sizeof(query), "SELECT shared, settings from %s " + sqlSafef(query, sizeof(query), "SELECT shared, settings from %s " "WHERE userName = '%s' AND sessionName = '%s'", namedSessionTable, encUserName, encSessionName); else - safef(query, sizeof(query), "SELECT shared from %s " + sqlSafef(query, sizeof(query), "SELECT shared from %s " "WHERE userName = '%s' AND sessionName = '%s'", namedSessionTable, encUserName, encSessionName); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { shared = atoi(row[0]); if (gotSettings) settings = cloneString(row[1]); sqlFreeResult(&sr); } else errAbort("doSessionChange: got no results from query:
\n%s\n", query); char *newName = cartOptionalString(cart, hgsNewSessionName); if (isNotEmpty(newName) && !sameString(sessionName, newName)) { char *encNewName = cgiEncodeFull(newName); - safef(query, sizeof(query), + sqlSafef(query, sizeof(query), "UPDATE %s set sessionName = '%s' WHERE userName = '%s' AND sessionName = '%s';", namedSessionTable, encNewName, encUserName, encSessionName); sqlUpdate(conn, query); dyStringPrintf(dyMessage, "Changed session name from %s to %s.\n", sessionName, newName); sessionName = newName; encSessionName = encNewName; renamePrefixedCartVar(hgsLoadPrefix, encOldSessionName, encNewName); renamePrefixedCartVar(hgsDeletePrefix, encOldSessionName, encNewName); } char varName[256]; safef(varName, sizeof(varName), hgsSharePrefix "%s", encOldSessionName); if (cgiBooleanDefined(varName)) { boolean newShared = cartBoolean(cart, varName); if (newShared != shared) { - safef(query, sizeof(query), + sqlSafef(query, sizeof(query), "UPDATE %s set shared = %d WHERE userName = '%s' AND sessionName = '%s';", namedSessionTable, newShared, encUserName, encSessionName); sqlUpdate(conn, query); dyStringPrintf(dyMessage, "Marked session %s as %s.
\n", htmlEncode(sessionName), (newShared ? "shared" : "unshared")); } cartRemove(cart, varName); char shadowVarName[512]; safef(shadowVarName, sizeof(shadowVarName), "%s%s", cgiBooleanShadowPrefix(), varName); cartRemove(cart, shadowVarName); } if (gotSettings) { struct hash *settingsHash = raFromString(settings); char *description = hashFindVal(settingsHash, "description"); char *newDescription = cartOptionalString(cart, hgsNewSessionDescription); if (newDescription != NULL) { - newDescription = replaceChars(newDescription, "\\", "\\\\\\\\"); - newDescription = replaceChars(newDescription, "\r", "\\\\r"); - newDescription = replaceChars(newDescription, "\n", "\\\\n"); + // newline escaping of \n is needed for ra syntax. + // not sure why \r and \ are being escaped, but it may be too late to change + // since there are probably records in the database that way now. + newDescription = replaceChars(newDescription, "\\", "\\\\"); + newDescription = replaceChars(newDescription, "\r", "\\r"); + newDescription = replaceChars(newDescription, "\n", "\\n"); } else newDescription = ""; - if (description != NULL) - description = replaceChars(description, "\\", "\\\\"); - else + if (description == NULL) description = ""; if (!sameString(description, newDescription)) { hashRemove(settingsHash, "description"); hashAdd(settingsHash, "description", newDescription); struct dyString *dyRa = dyStringNew(512); struct hashEl *hel = hashElListHash(settingsHash); while (hel != NULL) { - if (sameString(hel->name, "description")) - dyStringPrintf(dyRa, "%s %s\n", hel->name, newDescription); - else dyStringPrintf(dyRa, "%s %s\n", hel->name, (char *)hel->val); hel = hel->next; } struct dyString *dyQuery = dyStringNew(1024); - dyStringPrintf(dyQuery, "UPDATE %s set settings = ", namedSessionTable); - dyStringQuoteString(dyQuery, '"', dyRa->string); - dyStringPrintf(dyQuery, "WHERE userName = '%s' AND sessionName = '%s';", - encUserName, encSessionName); + sqlDyStringPrintf(dyQuery, "UPDATE %s set settings = '%s' " + "WHERE userName = '%s' AND sessionName = '%s';", + namedSessionTable, dyRa->string, encUserName, encSessionName); sqlUpdate(conn, dyQuery->string); dyStringPrintf(dyMessage, "Updated description of %s.\n", sessionName); } } if (isEmpty(dyMessage->string)) dyStringPrintf(dyMessage, "No changes to session %s.\n", sessionName); dyStringPrintf(dyMessage, "%s %s", getSessionLink(encUserName, encSessionName), getSessionEmailLink(encUserName, encSessionName)); return dyStringCannibalize(&dyMessage); } void hgSession() /* hgSession - Interface with wiki login and do session saving/loading.