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("
session name | created on | use this session | "
"delete this session | share with others? | link to session | "
"send to | ");
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("
");
@@ -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. |