/* Disconnect from the DBMS. */ int cllDisconnect(icatSessionStruct *icss) { RETCODE stat; HDBC myHdbc; int i; myHdbc = icss->connectPtr; i = cllCheckPending("", 1, icss->databaseType); if (i==1) { i = cllExecSqlNoResult(icss, "commit"); /* auto commit any pending SQLs, including the Audit ones */ /* Nothing to do if it fails */ } stat = SQLDisconnect(myHdbc); if (stat != SQL_SUCCESS) { rodsLog(LOG_ERROR, "cllDisconnect: SQLDisconnect failed: %d", stat); return(-1); } stat = SQLFreeConnect(myHdbc); if (stat != SQL_SUCCESS) { rodsLog(LOG_ERROR, "cllDisconnect: SQLFreeConnect failed: %d", stat); return(-2); } icss->connectPtr = myHdbc; return(0); }
int cmlTicketUpdateWriteBytes(char *ticketStr, char *dataSize, char *objectId, icatSessionStruct *icss) { int status, i; char *cVal[10]; int iVal[10]; char ticketId[NAME_LEN]=""; char writeByteCount[NAME_LEN]=""; char writeByteLimit[NAME_LEN]=""; rodsLong_t iWriteByteCount=0; rodsLong_t iWriteByteLimit=0; rodsLong_t iDataSize; char myWriteByteCount[NAME_LEN]; rodsLong_t iNewByteCount; iDataSize = atoll(dataSize); if (iDataSize == 0) return(0); for (i=0;i<10;i++) { iVal[i]=NAME_LEN; } cVal[0]=ticketId; cVal[1]=writeByteCount; cVal[2]=writeByteLimit; if (logSQL_CML!=0) rodsLog(LOG_SQL, "cmlTicketUpdateWriteBytes SQL 1 "); status = cmlGetStringValuesFromSql( "select ticket_id, write_byte_count, write_byte_limit from R_TICKET_MAIN TM, R_DATA_MAIN DM where TM.ticket_type = 'write' and TM.ticket_string = ? and (TM.object_id=? or (TM.object_id=DM.coll_id and DM.data_id=?))", cVal, iVal, 3, ticketStr, objectId, objectId, icss); if (status != 0) return(status); iWriteByteLimit = atoll(writeByteLimit); iWriteByteCount = atoll(writeByteCount); if (iWriteByteLimit==0) return(0); iNewByteCount = iWriteByteCount + iDataSize; snprintf(myWriteByteCount, sizeof myWriteByteCount, "%lld", iNewByteCount); cllBindVars[cllBindVarCount++]=myWriteByteCount; cllBindVars[cllBindVarCount++]=ticketId; if (logSQL_CML!=0) rodsLog(LOG_SQL, "cmlTicketUpdateWriteBytes SQL 2 "); status = cmlExecuteNoAnswerSql( "update R_TICKET_MAIN set write_byte_count=? where ticket_id=?", icss); if (status != 0) return(status); #ifndef ORA_ICAT /* as with auditing, do a commit on disconnect if needed */ cllCheckPending("",2, icss->databaseType); #endif return(0); }
int cmlAudit2(int actionId, char *dataId, char *userName, char *zoneName, char *accessLevel, icatSessionStruct *icss) { char myTime[50]; char actionIdStr[50]; int status; if (auditEnabled==0) return(0); if (logSQL_CML!=0) rodsLog(LOG_SQL, "cmlAudit2 SQL 1 "); getNowStr(myTime); snprintf(actionIdStr, sizeof actionIdStr, "%d", actionId); cllBindVars[0]=dataId; cllBindVars[1]=userName; cllBindVars[2]=zoneName; cllBindVars[3]=actionIdStr; cllBindVars[4]=accessLevel; cllBindVars[5]=myTime; cllBindVars[6]=myTime; cllBindVarCount=7; status = cmlExecuteNoAnswerSql( "insert into R_OBJT_AUDIT (object_id, user_id, action_id, r_comment, create_ts, modify_ts) values (?, (select user_id from R_USER_MAIN where user_name=? and zone_name=?), ?, ?, ?, ?)", icss); if (status != 0) { rodsLog(LOG_NOTICE, "cmlAudit2 insert failure %d", status); } #ifdef ORA_ICAT #else else { cllCheckPending("",2, icss->databaseType); /* Indicate that this was an audit SQL and so should be committed on disconnect if still pending. */ } #endif return(status); }
/* Audit - record auditing information */ int cmlAudit5(int actionId, char *objId, char *userId, char *comment, icatSessionStruct *icss) { char myTime[50]; char actionIdStr[50]; int status; if (auditEnabled==0) return(0); getNowStr(myTime); snprintf(actionIdStr, sizeof actionIdStr, "%d", actionId); cllBindVars[0]=objId; cllBindVars[1]=userId; cllBindVars[2]=actionIdStr; cllBindVars[3]=comment; cllBindVars[4]=myTime; cllBindVars[5]=myTime; cllBindVarCount=6; status = cmlExecuteNoAnswerSql( "insert into R_OBJT_AUDIT (object_id, user_id, action_id, r_comment, create_ts, modify_ts) values (?,?,?,?,?,?)", icss); if (status != 0) { rodsLog(LOG_NOTICE, "cmlAudit5 insert failure %d", status); } #ifdef ORA_ICAT #else else { cllCheckPending("",2, icss->databaseType); /* Indicate that this was an audit SQL and so should be committed on disconnect if still pending. */ } #endif return(status); }
int cmlAudit4(int actionId, char *sql, char *sqlParm, char *userName, char *zoneName, char *comment, icatSessionStruct *icss) { char myTime[50]; char actionIdStr[50]; char myComment[AUDIT_COMMENT_MAX_SIZE+10]; char mySQL[MAX_SQL_SIZE]; int status; int i; if (auditEnabled==0) return(0); getNowStr(myTime); snprintf(actionIdStr, sizeof actionIdStr, "%d", actionId); /* Truncate the comment if necessary (or else SQL will fail)*/ myComment[AUDIT_COMMENT_MAX_SIZE-1]='\0'; strncpy(myComment, comment, AUDIT_COMMENT_MAX_SIZE-1); if (zoneName[0]=='\0') { /* This no longer seems to occur. I'm leaving the code in place (just in case) but I'm removing the rodsLog call so the ICAT test suite does not require it to be tested. */ /* if (logSQL_CML!=0) rodsLog(LOG_SQL, "cmlA---udit4 S--QL 1 "); */ snprintf(mySQL, MAX_SQL_SIZE, "insert into R_OBJT_AUDIT (object_id, user_id, action_id, r_comment, create_ts, modify_ts) values ((%s), (select user_id from R_USER_MAIN where user_name=? and zone_name=(select zone_name from R_ZONE_MAIN where zone_type_name='local')), ?, ?, ?, ?)", sql); i=0; if (sqlParm[0]!='\0') { cllBindVars[i++]=sqlParm; } cllBindVars[i++]=userName; cllBindVars[i++]=actionIdStr; cllBindVars[i++]=myComment; cllBindVars[i++]=myTime; cllBindVars[i++]=myTime; cllBindVarCount=i; status = cmlExecuteNoAnswerSql(mySQL,icss); } else { if (logSQL_CML!=0) rodsLog(LOG_SQL, "cmlAudit4 SQL 2 "); snprintf(mySQL, MAX_SQL_SIZE, "insert into R_OBJT_AUDIT (object_id, user_id, action_id, r_comment, create_ts, modify_ts) values ((%s), (select user_id from R_USER_MAIN where user_name=? and zone_name=?), ?, ?, ?, ?)", sql); i=0; if (sqlParm[0]!='\0') { cllBindVars[i++]=sqlParm; } cllBindVars[i++]=userName; cllBindVars[i++]=zoneName; cllBindVars[i++]=actionIdStr; cllBindVars[i++]=myComment; cllBindVars[i++]=myTime; cllBindVars[i++]=myTime; cllBindVarCount=i; status = cmlExecuteNoAnswerSql(mySQL,icss); } if (status != 0) { rodsLog(LOG_NOTICE, "cmlAudit4 insert failure %d", status); } #ifdef ORA_ICAT #else else { cllCheckPending("",2, icss->databaseType); /* Indicate that this was an audit SQL and so should be committed on disconnect if still pending. */ } #endif return(status); }
/* Check access via a Ticket to a data-object or collection */ int checkObjIdByTicket(char *dataId, char *accessLevel, char *ticketStr, char *ticketHost, char *userName, char *userZone, icatSessionStruct *icss) { int status, i; char *cVal[10]; int iVal[10]; char ticketId[NAME_LEN]=""; char usesCount[NAME_LEN]=""; char usesLimit[NAME_LEN]=""; char ticketExpiry[NAME_LEN]=""; char restrictions[NAME_LEN]=""; char writeFileCount[NAME_LEN]=""; char writeFileLimit[NAME_LEN]=""; char writeByteCount[NAME_LEN]=""; char writeByteLimit[NAME_LEN]=""; int iUsesCount=0; int iUsesLimit=0; int iWriteFileCount=0; int iWriteFileLimit=0; int iWriteByteCount=0; int iWriteByteLimit=0; char myUsesCount[NAME_LEN]; char myWriteFileCount[NAME_LEN]; rodsLong_t intDataId; static rodsLong_t previousDataId1=0; static rodsLong_t previousDataId2=0; static char prevTicketId[50]=""; #if 0 rodsLog(LOG_NOTICE, "checkObjIdByTicket debug dataId=%s accessLevel=%s", dataId, accessLevel); #endif for (i=0;i<10;i++) { iVal[i]=NAME_LEN; } cVal[0]=ticketId; cVal[1]=usesLimit; cVal[2]=usesCount; cVal[3]=ticketExpiry; cVal[4]=restrictions; if (strncmp(accessLevel, "modify", 6) == 0) { if (logSQL_CML!=0) rodsLog(LOG_SQL, "checkObjIdByTicket SQL 1 "); /* ticket must also be of type 'write', and get the writeFileCount and writeFileLimit */ cVal[5]=writeFileCount; cVal[6]=writeFileLimit; cVal[7]=writeByteCount; cVal[8]=writeByteLimit; status = cmlGetStringValuesFromSql( "select ticket_id, uses_limit, uses_count, ticket_expiry_ts, restrictions, write_file_count, write_file_limit, write_byte_count, write_byte_limit from R_TICKET_MAIN TM, R_DATA_MAIN DM where TM.ticket_type = 'write' and TM.ticket_string = ? and (TM.object_id=? or (TM.object_id=DM.coll_id and DM.data_id=?))", cVal, iVal, 9, ticketStr, dataId, dataId, icss); } else { /* don't check ticket type, 'read' or 'write' is fine */ if (logSQL_CML!=0) rodsLog(LOG_SQL, "checkObjIdByTicket SQL 2 "); status = cmlGetStringValuesFromSql( "select ticket_id, uses_limit, uses_count, ticket_expiry_ts, restrictions from R_TICKET_MAIN TM, R_DATA_MAIN DM where TM.ticket_string = ? and (TM.object_id=? or (TM.object_id=DM.coll_id and DM.data_id=?))", cVal, iVal, 5, ticketStr, dataId, dataId, icss); } if (status != 0) return (CAT_TICKET_INVALID); if (strncmp(ticketId, prevTicketId, sizeof(prevTicketId)) != 0) { strncpy(prevTicketId, ticketId, sizeof(prevTicketId)); status = cmlAudit3(AU_USE_TICKET, ticketId, userName, userZone, ticketStr, icss); if (status != 0) return(status); } if (ticketExpiry[0]!='\0') { rodsLong_t ticketExp, now; char myTime[50]; ticketExp = atoll(ticketExpiry); if (ticketExp > 0) { getNowStr(myTime); now = atoll(myTime); if (now > ticketExp) { return(CAT_TICKET_EXPIRED); } } } status = cmlCheckTicketRestrictions(ticketId, ticketHost, userName, userZone, icss); if (status != 0) return(status); if (strncmp(accessLevel, "modify", 6) == 0) { iWriteByteLimit = atoi(writeByteLimit); if (iWriteByteLimit > 0) { iWriteByteCount = atoi(writeByteCount); if (iWriteByteCount > iWriteByteLimit) { return(CAT_TICKET_WRITE_BYTES_EXCEEDED); } } iWriteFileLimit = atoi(writeFileLimit); if (iWriteFileLimit > 0) { iWriteFileCount = atoi(writeFileCount); if (iWriteFileCount >= iWriteFileLimit) { return(CAT_TICKET_WRITE_USES_EXCEEDED); } intDataId = atoll(dataId); /* Don't update a second time if this id matches the last one */ if (previousDataId1!=intDataId) { iWriteFileCount++; snprintf(myWriteFileCount, sizeof myWriteFileCount, "%d", iWriteFileCount); cllBindVars[cllBindVarCount++]=myWriteFileCount; cllBindVars[cllBindVarCount++]=ticketId; if (logSQL_CML!=0) rodsLog(LOG_SQL, "checkObjIdByTicket SQL 3 "); status = cmlExecuteNoAnswerSql( "update R_TICKET_MAIN set write_file_count=? where ticket_id=?", icss); if (status != 0) return(status); #ifndef ORA_ICAT /* as with auditing, do a commit on disconnect if needed */ cllCheckPending("",2, icss->databaseType); #endif } previousDataId1=intDataId; } } iUsesLimit = atoi(usesLimit); if (iUsesLimit > 0) { iUsesCount = atoi(usesCount); if (iUsesCount >= iUsesLimit) { return(CAT_TICKET_USES_EXCEEDED); } intDataId = atoll(dataId); /* Don't update a second time if this id matches the last one */ if (previousDataId2!=intDataId) { iUsesCount++; snprintf(myUsesCount, sizeof myUsesCount, "%d", iUsesCount); cllBindVars[cllBindVarCount++]=myUsesCount; cllBindVars[cllBindVarCount++]=ticketId; if (logSQL_CML!=0) rodsLog(LOG_SQL, "checkObjIdByTicket SQL 4 "); status = cmlExecuteNoAnswerSql( "update R_TICKET_MAIN set uses_count=? where ticket_id=?", icss); if (status != 0) return(status); #ifndef ORA_ICAT /* as with auditing, do a commit on disconnect if needed*/ cllCheckPending("",2, icss->databaseType); #endif } previousDataId2=intDataId; } return(0); }
/* Execute a SQL command which has no resulting table. With optional bind variables. If option is 1, skip the bind variables. */ int _cllExecSqlNoResult(icatSessionStruct *icss, char *sql, int option) { RETCODE stat; HDBC myHdbc; HSTMT myHstmt; int result; char *status; SQL_INT_OR_LEN rowCount; #ifdef NEW_ODBC int i; #endif noResultRowCount=0; rowCount=0; myHdbc = icss->connectPtr; rodsLog(LOG_DEBUG1, sql); stat = SQLAllocStmt(myHdbc, &myHstmt); if (stat != SQL_SUCCESS) { rodsLog(LOG_ERROR, "_cllExecSqlNoResult: SQLAllocStmt failed: %d", stat); return(-1); } #if 0 if (bindVar1 != 0 && *bindVar1 != '\0') { stat = SQLBindParameter(myHstmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_C_SBIGINT, 0, 0, 0, 0, 0); if (stat != SQL_SUCCESS) { rodsLog(LOG_ERROR, "_cllExecSqlNoResult: SQLAllocStmt failed: %d", stat); return(-1); } } #endif if (option==0) { if (bindTheVariables(myHstmt, sql) != 0) return(-1); } rodsLogSql(sql); stat = SQLExecDirect(myHstmt, (unsigned char *)sql, SQL_NTS); status = "UNKNOWN"; if (stat == SQL_SUCCESS) status= "SUCCESS"; if (stat == SQL_SUCCESS_WITH_INFO) status="SUCCESS_WITH_INFO"; if (stat == SQL_NO_DATA_FOUND) status="NO_DATA"; if (stat == SQL_ERROR) status="SQL_ERROR"; if (stat == SQL_INVALID_HANDLE) status="HANDLE_ERROR"; rodsLogSqlResult(status); if (stat == SQL_SUCCESS || stat == SQL_SUCCESS_WITH_INFO || stat == SQL_NO_DATA_FOUND) { cllCheckPending(sql, 0, icss->databaseType); result = 0; if (stat == SQL_NO_DATA_FOUND) result = CAT_SUCCESS_BUT_WITH_NO_INFO; #ifdef NEW_ODBC /* ODBC says that if statement is not UPDATE, INSERT, or DELETE then SQLRowCount may return anything. So for BEGIN, COMMIT and ROLLBACK we don't want to call it but just return OK. */ if ( ! cmp_stmt(sql,"begin") && ! cmp_stmt(sql,"commit") && ! cmp_stmt(sql,"rollback") ) { /* Doesn't seem to return SQL_NO_DATA_FOUND, so check */ i = SQLRowCount (myHstmt, (SQL_INT_OR_LEN *)&rowCount); if (i) { /* error getting rowCount???, just call it no_info */ result = CAT_SUCCESS_BUT_WITH_NO_INFO; } if (rowCount==0) result = CAT_SUCCESS_BUT_WITH_NO_INFO; } #else rowCount=0; /* avoid compiler warning */ #endif } else { if (option==0) { logTheBindVariables(LOG_NOTICE); } rodsLog(LOG_NOTICE,"_cllExecSqlNoResult: SQLExecDirect error: %d sql:%s", stat, sql); result = logPsgError(LOG_NOTICE, icss->environPtr, myHdbc, myHstmt, icss->databaseType); } stat = SQLFreeStmt(myHstmt, SQL_DROP); if (stat != SQL_SUCCESS) { rodsLog(LOG_ERROR, "_cllExecSqlNoResult: SQLFreeStmt error: %d", stat); } noResultRowCount = rowCount; return(result); }