int BusyWithClassicConnection(EvalContext *ctx, ServerConnectionState *conn) { time_t tloc, trem = 0; char recvbuffer[CF_BUFSIZE + CF_BUFEXT], check[CF_BUFSIZE]; char sendbuffer[CF_BUFSIZE] = { 0 }; char filename[CF_BUFSIZE], buffer[CF_BUFSIZE], args[CF_BUFSIZE], out[CF_BUFSIZE]; long time_no_see = 0; unsigned int len = 0; int drift, plainlen, received, encrypted = 0; ServerFileGetState get_args; Item *classes; memset(recvbuffer, 0, CF_BUFSIZE + CF_BUFEXT); memset(&get_args, 0, sizeof(get_args)); received = ReceiveTransaction(conn->conn_info, recvbuffer, NULL); if (received == -1 || received == 0) { return false; } if (strlen(recvbuffer) == 0) { Log(LOG_LEVEL_WARNING, "Got NULL transmission, skipping!"); return true; } /* Don't process request if we're signalled to exit. */ if (IsPendingTermination()) { return false; } ProtocolCommandClassic command = GetCommandClassic(recvbuffer); switch (command) { /* Plain text authentication; this MUST be the first command client using classic protocol is sending. */ case PROTOCOL_COMMAND_AUTH_PLAIN: SetConnectionData(conn, (char *) (recvbuffer + strlen("CAUTH "))); if (conn->username == NULL || IsUserNameValid(conn->username) == false) { Log(LOG_LEVEL_INFO, "Client is sending wrong username: '******'", conn->username); RefuseAccess(conn, recvbuffer); return false; } /* This is used only for forcing correct state of state machine while connecting and authenticating user using classic protocol. */ conn->user_data_set = true; return true; /* This MUST be exactly second command client using classic protocol is sending. This is where key agreement takes place. */ case PROTOCOL_COMMAND_AUTH_SECURE: /* First command was ommited by client; this is protocol violation. */ if (!conn->user_data_set) { Log(LOG_LEVEL_INFO, "Client is not verified; rejecting connection"); RefuseAccess(conn, recvbuffer); return false; } conn->rsa_auth = AuthenticationDialogue(conn, recvbuffer, received); if (!conn->rsa_auth) { Log(LOG_LEVEL_INFO, "Auth dialogue error"); RefuseAccess(conn, recvbuffer); return false; } return true; default: break; } /* At this point we should have both user_data_set and rsa_auth set to perform any operation. We can check only for second one as without first it won't be set up. */ if (!conn->rsa_auth) { Log(LOG_LEVEL_INFO, "Server refusal due to no RSA authentication [command: %d]", command); RefuseAccess(conn, recvbuffer); return false; } /* We have to have key at this point. */ assert(conn->session_key); /* At this point we can safely do next switch and make sure user is authenticated. */ switch (command) { case PROTOCOL_COMMAND_EXEC: memset(args, 0, CF_BUFSIZE); sscanf(recvbuffer, "EXEC %255[^\n]", args); if (!AllowedUser(conn->username)) { Log(LOG_LEVEL_INFO, "Server refusal due to non-allowed user"); RefuseAccess(conn, recvbuffer); return false; } if (!AccessControl(ctx, CommandArg0(CFRUNCOMMAND), conn, false)) { Log(LOG_LEVEL_INFO, "Server refusal due to denied access to requested object"); RefuseAccess(conn, recvbuffer); return false; } if (!MatchClasses(ctx, conn)) { Log(LOG_LEVEL_INFO, "Server refusal due to failed class/context match"); Terminate(conn->conn_info); return false; } DoExec(ctx, conn, args); Terminate(conn->conn_info); return false; case PROTOCOL_COMMAND_VERSION: snprintf(sendbuffer, sizeof(sendbuffer), "OK: %s", Version()); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return conn->user_data_set; case PROTOCOL_COMMAND_GET: memset(filename, 0, CF_BUFSIZE); sscanf(recvbuffer, "GET %d %[^\n]", &(get_args.buf_size), filename); if ((get_args.buf_size < 0) || (get_args.buf_size > CF_BUFSIZE)) { Log(LOG_LEVEL_INFO, "GET buffer out of bounds"); RefuseAccess(conn, recvbuffer); return false; } if (!AccessControl(ctx, filename, conn, false)) { Log(LOG_LEVEL_INFO, "Access denied to get object"); RefuseAccess(conn, recvbuffer); return true; } memset(sendbuffer, 0, sizeof(sendbuffer)); if (get_args.buf_size >= CF_BUFSIZE) { get_args.buf_size = 2048; } get_args.connect = conn; get_args.encrypt = false; get_args.replybuff = sendbuffer; get_args.replyfile = filename; CfGetFile(&get_args); return true; case PROTOCOL_COMMAND_GET_SECURE: memset(buffer, 0, CF_BUFSIZE); sscanf(recvbuffer, "SGET %u %d", &len, &(get_args.buf_size)); if (received != len + CF_PROTO_OFFSET) { Log(LOG_LEVEL_VERBOSE, "Protocol error SGET"); RefuseAccess(conn, recvbuffer); return false; } plainlen = DecryptString(conn->encryption_type, recvbuffer + CF_PROTO_OFFSET, buffer, conn->session_key, len); cfscanf(buffer, strlen("GET"), strlen("dummykey"), check, sendbuffer, filename); if (strcmp(check, "GET") != 0) { Log(LOG_LEVEL_INFO, "SGET/GET problem"); RefuseAccess(conn, recvbuffer); return true; } if ((get_args.buf_size < 0) || (get_args.buf_size > 8192)) { Log(LOG_LEVEL_INFO, "SGET bounding error"); RefuseAccess(conn, recvbuffer); return false; } if (get_args.buf_size >= CF_BUFSIZE) { get_args.buf_size = 2048; } Log(LOG_LEVEL_DEBUG, "Confirm decryption, and thus validity of caller"); Log(LOG_LEVEL_DEBUG, "SGET '%s' with blocksize %d", filename, get_args.buf_size); if (!AccessControl(ctx, filename, conn, true)) { Log(LOG_LEVEL_INFO, "Access control error"); RefuseAccess(conn, recvbuffer); return false; } memset(sendbuffer, 0, sizeof(sendbuffer)); get_args.connect = conn; get_args.encrypt = true; get_args.replybuff = sendbuffer; get_args.replyfile = filename; CfEncryptGetFile(&get_args); return true; case PROTOCOL_COMMAND_OPENDIR_SECURE: memset(buffer, 0, CF_BUFSIZE); sscanf(recvbuffer, "SOPENDIR %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_VERBOSE, "Protocol error OPENDIR: %d", len); RefuseAccess(conn, recvbuffer); return false; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); if (strncmp(recvbuffer, "OPENDIR", 7) != 0) { Log(LOG_LEVEL_INFO, "Opendir failed to decrypt"); RefuseAccess(conn, recvbuffer); return true; } memset(filename, 0, CF_BUFSIZE); sscanf(recvbuffer, "OPENDIR %[^\n]", filename); if (!AccessControl(ctx, filename, conn, true)) /* opendir don't care about privacy */ { Log(LOG_LEVEL_INFO, "Access error"); RefuseAccess(conn, recvbuffer); return false; } CfSecOpenDirectory(conn, sendbuffer, filename); return true; case PROTOCOL_COMMAND_OPENDIR: memset(filename, 0, CF_BUFSIZE); sscanf(recvbuffer, "OPENDIR %[^\n]", filename); if (!AccessControl(ctx, filename, conn, true)) /* opendir don't care about privacy */ { Log(LOG_LEVEL_INFO, "DIR access error"); RefuseAccess(conn, recvbuffer); return false; } CfOpenDirectory(conn, sendbuffer, filename); return true; case PROTOCOL_COMMAND_SYNC_SECURE: memset(buffer, 0, CF_BUFSIZE); sscanf(recvbuffer, "SSYNCH %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_VERBOSE, "Protocol error SSYNCH: %d", len); RefuseAccess(conn, recvbuffer); return false; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); if (plainlen < 0) { DebugBinOut((char *) conn->session_key, 32, "Session key"); Log(LOG_LEVEL_ERR, "Bad decrypt (%d)", len); } if (strncmp(recvbuffer, "SYNCH", 5) != 0) { Log(LOG_LEVEL_INFO, "No synch"); RefuseAccess(conn, recvbuffer); return true; } /* roll through, no break */ case PROTOCOL_COMMAND_SYNC: memset(filename, 0, CF_BUFSIZE); sscanf(recvbuffer, "SYNCH %ld STAT %[^\n]", &time_no_see, filename); trem = (time_t) time_no_see; if ((time_no_see == 0) || (filename[0] == '\0')) { break; } if ((tloc = time((time_t *) NULL)) == -1) { Log(LOG_LEVEL_INFO, "Couldn't read system clock. (time: %s)", GetErrorStr()); SendTransaction(conn->conn_info, "BAD: clocks out of synch", 0, CF_DONE); return true; } drift = (int) (tloc - trem); if (!AccessControl(ctx, filename, conn, true)) { Log(LOG_LEVEL_INFO, "Access control in sync"); RefuseAccess(conn, recvbuffer); return true; } if (DENYBADCLOCKS && (drift * drift > CLOCK_DRIFT * CLOCK_DRIFT)) { snprintf(sendbuffer, sizeof(sendbuffer), "BAD: Clocks are too far unsynchronized %ld/%ld", (long) tloc, (long) trem); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return true; } else { Log(LOG_LEVEL_DEBUG, "Clocks were off by %ld", (long) tloc - (long) trem); StatFile(conn, sendbuffer, filename); } return true; case PROTOCOL_COMMAND_MD5_SECURE: sscanf(recvbuffer, "SMD5 %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_INFO, "Decryption error"); RefuseAccess(conn, recvbuffer); return true; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); if (strncmp(recvbuffer, "MD5", 3) != 0) { Log(LOG_LEVEL_INFO, "MD5 protocol error"); RefuseAccess(conn, recvbuffer); return false; } /* roll through, no break */ case PROTOCOL_COMMAND_MD5: CompareLocalHash(conn, sendbuffer, recvbuffer); return true; case PROTOCOL_COMMAND_VAR_SECURE: sscanf(recvbuffer, "SVAR %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_INFO, "Decrypt error SVAR"); RefuseAccess(conn, "decrypt error SVAR"); return true; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); encrypted = true; if (strncmp(recvbuffer, "VAR", 3) != 0) { Log(LOG_LEVEL_INFO, "VAR protocol defect"); RefuseAccess(conn, "decryption failure"); return false; } /* roll through, no break */ case PROTOCOL_COMMAND_VAR: if (!LiteralAccessControl(ctx, recvbuffer, conn, encrypted)) { Log(LOG_LEVEL_INFO, "Literal access failure"); RefuseAccess(conn, recvbuffer); return false; } GetServerLiteral(ctx, conn, sendbuffer, recvbuffer, encrypted); return true; case PROTOCOL_COMMAND_CONTEXT_SECURE: sscanf(recvbuffer, "SCONTEXT %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_INFO, "Decrypt error SCONTEXT, len,received = %d,%d", len, received); RefuseAccess(conn, "decrypt error SCONTEXT"); return true; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); encrypted = true; if (strncmp(recvbuffer, "CONTEXT", 7) != 0) { Log(LOG_LEVEL_INFO, "CONTEXT protocol defect..."); RefuseAccess(conn, "Decryption failed?"); return false; } /* roll through, no break */ case PROTOCOL_COMMAND_CONTEXT: if ((classes = ContextAccessControl(ctx, recvbuffer, conn, encrypted)) == NULL) { Log(LOG_LEVEL_INFO, "Context access failure on %s", recvbuffer); RefuseAccess(conn, recvbuffer); return false; } ReplyServerContext(conn, encrypted, classes); return true; case PROTOCOL_COMMAND_QUERY_SECURE: sscanf(recvbuffer, "SQUERY %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_INFO, "Decrypt error SQUERY"); RefuseAccess(conn, "decrypt error SQUERY"); return true; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); if (strncmp(recvbuffer, "QUERY", 5) != 0) { Log(LOG_LEVEL_INFO, "QUERY protocol defect"); RefuseAccess(conn, "decryption failure"); return false; } if (!LiteralAccessControl(ctx, recvbuffer, conn, true)) { Log(LOG_LEVEL_INFO, "Query access failure"); RefuseAccess(conn, recvbuffer); return false; } if (GetServerQuery(conn, recvbuffer, true)) /* always encrypt */ { return true; } break; case PROTOCOL_COMMAND_CALL_ME_BACK: sscanf(recvbuffer, "SCALLBACK %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_INFO, "Decrypt error CALL_ME_BACK"); RefuseAccess(conn, "decrypt error CALL_ME_BACK"); return true; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); if (strncmp(recvbuffer, "CALL_ME_BACK collect_calls", strlen("CALL_ME_BACK collect_calls")) != 0) { Log(LOG_LEVEL_INFO, "CALL_ME_BACK protocol defect"); RefuseAccess(conn, "decryption failure"); return false; } if (!LiteralAccessControl(ctx, recvbuffer, conn, true)) { Log(LOG_LEVEL_INFO, "Query access failure"); RefuseAccess(conn, recvbuffer); return false; } if (ReceiveCollectCall(conn)) { return true; } case PROTOCOL_COMMAND_AUTH_PLAIN: case PROTOCOL_COMMAND_AUTH_SECURE: case PROTOCOL_COMMAND_AUTH: case PROTOCOL_COMMAND_CONTEXTS: case PROTOCOL_COMMAND_BAD: Log(LOG_LEVEL_WARNING, "Unexpected protocol command"); } strcpy(sendbuffer, "BAD: Request denied"); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); Log(LOG_LEVEL_INFO, "Closing connection, due to request: '%s'", recvbuffer); return false; }
static void test_command_parser(void) { ProtocolCommandClassic parsed = PROTOCOL_COMMAND_BAD; ProtocolCommandClassic expected = PROTOCOL_COMMAND_BAD; /* * Test all the commands, one by one. */ // EXEC expected = PROTOCOL_COMMAND_EXEC; parsed = GetCommandClassic("EXEC"); assert_int_equal(expected, parsed); // AUTH expected = PROTOCOL_COMMAND_AUTH; parsed = GetCommandClassic("AUTH"); assert_int_equal(expected, parsed); // GET expected = PROTOCOL_COMMAND_GET; parsed = GetCommandClassic("GET"); assert_int_equal(expected, parsed); // OPENDIR expected = PROTOCOL_COMMAND_OPENDIR; parsed = GetCommandClassic("OPENDIR"); assert_int_equal(expected, parsed); // SYNCH expected = PROTOCOL_COMMAND_SYNC; parsed = GetCommandClassic("SYNCH"); assert_int_equal(expected, parsed); // CLASSES expected = PROTOCOL_COMMAND_CONTEXTS; parsed = GetCommandClassic("CLASSES"); assert_int_equal(expected, parsed); // MD5 expected = PROTOCOL_COMMAND_MD5; parsed = GetCommandClassic("MD5"); assert_int_equal(expected, parsed); // SMD5 expected = PROTOCOL_COMMAND_MD5_SECURE; parsed = GetCommandClassic("SMD5"); assert_int_equal(expected, parsed); // CAUTH expected = PROTOCOL_COMMAND_AUTH_CLEAR; parsed = GetCommandClassic("CAUTH"); assert_int_equal(expected, parsed); // SAUTH expected = PROTOCOL_COMMAND_AUTH_SECURE; parsed = GetCommandClassic("SAUTH"); assert_int_equal(expected, parsed); // SSYNCH expected = PROTOCOL_COMMAND_SYNC_SECURE; parsed = GetCommandClassic("SSYNCH"); assert_int_equal(expected, parsed); // SGET expected = PROTOCOL_COMMAND_GET_SECURE; parsed = GetCommandClassic("SGET"); assert_int_equal(expected, parsed); // VERSION expected = PROTOCOL_COMMAND_VERSION; parsed = GetCommandClassic("VERSION"); assert_int_equal(expected, parsed); // SOPENDIR expected = PROTOCOL_COMMAND_OPENDIR_SECURE; parsed = GetCommandClassic("SOPENDIR"); assert_int_equal(expected, parsed); // VAR expected = PROTOCOL_COMMAND_VAR; parsed = GetCommandClassic("VAR"); assert_int_equal(expected, parsed); // SVAR expected = PROTOCOL_COMMAND_VAR_SECURE; parsed = GetCommandClassic("SVAR"); assert_int_equal(expected, parsed); // CONTEXT expected = PROTOCOL_COMMAND_CONTEXT; parsed = GetCommandClassic("CONTEXT"); assert_int_equal(expected, parsed); // SCONTEXT expected = PROTOCOL_COMMAND_CONTEXT_SECURE; parsed = GetCommandClassic("SCONTEXT"); assert_int_equal(expected, parsed); // SQUERY expected = PROTOCOL_COMMAND_QUERY_SECURE; parsed = GetCommandClassic("SQUERY"); assert_int_equal(expected, parsed); // SCALLBACK expected = PROTOCOL_COMMAND_CALL_ME_BACK; parsed = GetCommandClassic("SCALLBACK"); assert_int_equal(expected, parsed); /* * Try using lowercase */ // EXEC expected = PROTOCOL_COMMAND_BAD; parsed = GetCommandClassic("exec"); assert_int_equal(expected, parsed); // AUTH parsed = GetCommandClassic("auth"); assert_int_equal(expected, parsed); // GET parsed = GetCommandClassic("get"); assert_int_equal(expected, parsed); // OPENDIR parsed = GetCommandClassic("opendir"); assert_int_equal(expected, parsed); // SYNCH parsed = GetCommandClassic("synch"); assert_int_equal(expected, parsed); // CLASSES parsed = GetCommandClassic("classes"); assert_int_equal(expected, parsed); // MD5 parsed = GetCommandClassic("md5"); assert_int_equal(expected, parsed); // SMD5 parsed = GetCommandClassic("smd5"); assert_int_equal(expected, parsed); // CAUTH parsed = GetCommandClassic("cauth"); assert_int_equal(expected, parsed); // SAUTH parsed = GetCommandClassic("sauth"); assert_int_equal(expected, parsed); // SSYNCH parsed = GetCommandClassic("synch"); assert_int_equal(expected, parsed); // SGET parsed = GetCommandClassic("sget"); assert_int_equal(expected, parsed); // VERSION parsed = GetCommandClassic("version"); assert_int_equal(expected, parsed); // SOPENDIR parsed = GetCommandClassic("sopendir"); assert_int_equal(expected, parsed); // VAR parsed = GetCommandClassic("var"); assert_int_equal(expected, parsed); // SVAR parsed = GetCommandClassic("svar"); assert_int_equal(expected, parsed); // CONTEXT parsed = GetCommandClassic("context"); assert_int_equal(expected, parsed); // SCONTEXT parsed = GetCommandClassic("scontext"); assert_int_equal(expected, parsed); // SQUERY parsed = GetCommandClassic("squery"); assert_int_equal(expected, parsed); // SCALLBACK parsed = GetCommandClassic("scallback"); assert_int_equal(expected, parsed); /* * Try the commands with something in front */ // EXEC expected = PROTOCOL_COMMAND_BAD; parsed = GetCommandClassic("eEXEC"); assert_int_equal(expected, parsed); // AUTH parsed = GetCommandClassic("aAUTH"); assert_int_equal(expected, parsed); // GET parsed = GetCommandClassic("gGET"); assert_int_equal(expected, parsed); // OPENDIR parsed = GetCommandClassic("oOPENDIR"); assert_int_equal(expected, parsed); // SYNCH parsed = GetCommandClassic("sSYNCH"); assert_int_equal(expected, parsed); // CLASSES parsed = GetCommandClassic("cCLASSES"); assert_int_equal(expected, parsed); // MD5 parsed = GetCommandClassic("mMD5"); assert_int_equal(expected, parsed); // SMD5 parsed = GetCommandClassic("sMD5"); assert_int_equal(expected, parsed); // CAUTH parsed = GetCommandClassic("cCAUTH"); assert_int_equal(expected, parsed); // SAUTH parsed = GetCommandClassic("sSAUTH"); assert_int_equal(expected, parsed); // SSYNCH parsed = GetCommandClassic("sSSYNCH"); assert_int_equal(expected, parsed); // SGET parsed = GetCommandClassic("sSGET"); assert_int_equal(expected, parsed); // VERSION parsed = GetCommandClassic("vVERSION"); assert_int_equal(expected, parsed); // SOPENDIR parsed = GetCommandClassic("sSOPENDIR"); assert_int_equal(expected, parsed); // VAR parsed = GetCommandClassic("vVAR"); assert_int_equal(expected, parsed); // SVAR parsed = GetCommandClassic("sSVAR"); assert_int_equal(expected, parsed); // CONTEXT parsed = GetCommandClassic("cCONTEXT"); assert_int_equal(expected, parsed); // SCONTEXT parsed = GetCommandClassic("sSCONTEXT"); assert_int_equal(expected, parsed); // SQUERY parsed = GetCommandClassic("sSQUERY"); assert_int_equal(expected, parsed); // SCALLBACK parsed = GetCommandClassic("sSCALLBACK"); assert_int_equal(expected, parsed); /* * Try the commands with something after them */ // EXEC expected = PROTOCOL_COMMAND_BAD; parsed = GetCommandClassic("EXECx"); assert_int_equal(expected, parsed); // AUTH parsed = GetCommandClassic("AUTHx"); assert_int_equal(expected, parsed); // GET parsed = GetCommandClassic("GETx"); assert_int_equal(expected, parsed); // OPENDIR parsed = GetCommandClassic("OPENDIRx"); assert_int_equal(expected, parsed); // SYNCH parsed = GetCommandClassic("SYNCHx"); assert_int_equal(expected, parsed); // CLASSES parsed = GetCommandClassic("CLASSESx"); assert_int_equal(expected, parsed); // MD5 parsed = GetCommandClassic("MD5x"); assert_int_equal(expected, parsed); // SMD5 parsed = GetCommandClassic("SMD5x"); assert_int_equal(expected, parsed); // CAUTH parsed = GetCommandClassic("CAUTHx"); assert_int_equal(expected, parsed); // SAUTH parsed = GetCommandClassic("SAUTHx"); assert_int_equal(expected, parsed); // SSYNCH parsed = GetCommandClassic("SSYNCHx"); assert_int_equal(expected, parsed); // SGET parsed = GetCommandClassic("SGETx"); assert_int_equal(expected, parsed); // VERSION parsed = GetCommandClassic("VERSIONx"); assert_int_equal(expected, parsed); // SOPENDIR parsed = GetCommandClassic("SOPENDIRx"); assert_int_equal(expected, parsed); // VAR parsed = GetCommandClassic("VARx"); assert_int_equal(expected, parsed); // SVAR parsed = GetCommandClassic("SVARx"); assert_int_equal(expected, parsed); // CONTEXT parsed = GetCommandClassic("CONTEXTx"); assert_int_equal(expected, parsed); // SCONTEXT parsed = GetCommandClassic("SCONTEXTx"); assert_int_equal(expected, parsed); // SQUERY parsed = GetCommandClassic("SQUERYx"); assert_int_equal(expected, parsed); // SCALLBACK parsed = GetCommandClassic("SCALLBACKx"); assert_int_equal(expected, parsed); /* * Try some common mispellings. */ // EXEC expected = PROTOCOL_COMMAND_BAD; parsed = GetCommandClassic("EXE"); assert_int_equal(expected, parsed); parsed = GetCommandClassic("EXECUTE"); assert_int_equal(expected, parsed); // AUTH parsed = GetCommandClassic("AUTHORIZATION"); assert_int_equal(expected, parsed); // SYNCH parsed = GetCommandClassic("SYNC"); assert_int_equal(expected, parsed); parsed = GetCommandClassic("SYNCHRONIZE"); assert_int_equal(expected, parsed); // CLASSES parsed = GetCommandClassic("CLASS"); assert_int_equal(expected, parsed); // CAUTH parsed = GetCommandClassic("CAUTHORIZATION"); assert_int_equal(expected, parsed); // SAUTH parsed = GetCommandClassic("SAUTHORIZATION"); assert_int_equal(expected, parsed); // SSYNCH parsed = GetCommandClassic("SSYNCHRONIZE"); assert_int_equal(expected, parsed); parsed = GetCommandClassic("SSYNC"); assert_int_equal(expected, parsed); // VERSION parsed = GetCommandClassic("V"); assert_int_equal(expected, parsed); // VAR parsed = GetCommandClassic("VARIABLE"); assert_int_equal(expected, parsed); // SVAR parsed = GetCommandClassic("SVARIABLE"); assert_int_equal(expected, parsed); /* * Finally, try the commands with a space and something else, they should be recognized" */ // EXEC expected = PROTOCOL_COMMAND_EXEC; parsed = GetCommandClassic("EXEC 123"); assert_int_equal(expected, parsed); // AUTH expected = PROTOCOL_COMMAND_AUTH; parsed = GetCommandClassic("AUTH 123"); assert_int_equal(expected, parsed); // GET expected = PROTOCOL_COMMAND_GET; parsed = GetCommandClassic("GET 123"); assert_int_equal(expected, parsed); // OPENDIR expected = PROTOCOL_COMMAND_OPENDIR; parsed = GetCommandClassic("OPENDIR 123"); assert_int_equal(expected, parsed); // SYNCH expected = PROTOCOL_COMMAND_SYNC; parsed = GetCommandClassic("SYNCH 123"); assert_int_equal(expected, parsed); // CLASSES expected = PROTOCOL_COMMAND_CONTEXTS; parsed = GetCommandClassic("CLASSES 123"); assert_int_equal(expected, parsed); // MD5 expected = PROTOCOL_COMMAND_MD5; parsed = GetCommandClassic("MD5 123"); assert_int_equal(expected, parsed); // SMD5 expected = PROTOCOL_COMMAND_MD5_SECURE; parsed = GetCommandClassic("SMD5 123"); assert_int_equal(expected, parsed); // CAUTH expected = PROTOCOL_COMMAND_AUTH_CLEAR; parsed = GetCommandClassic("CAUTH 123"); assert_int_equal(expected, parsed); // SAUTH expected = PROTOCOL_COMMAND_AUTH_SECURE; parsed = GetCommandClassic("SAUTH 123"); assert_int_equal(expected, parsed); // SSYNCH expected = PROTOCOL_COMMAND_SYNC_SECURE; parsed = GetCommandClassic("SSYNCH 123"); assert_int_equal(expected, parsed); // SGET expected = PROTOCOL_COMMAND_GET_SECURE; parsed = GetCommandClassic("SGET 123"); assert_int_equal(expected, parsed); // VERSION expected = PROTOCOL_COMMAND_VERSION; parsed = GetCommandClassic("VERSION 123"); assert_int_equal(expected, parsed); // SOPENDIR expected = PROTOCOL_COMMAND_OPENDIR_SECURE; parsed = GetCommandClassic("SOPENDIR 123"); assert_int_equal(expected, parsed); // VAR expected = PROTOCOL_COMMAND_VAR; parsed = GetCommandClassic("VAR 123"); assert_int_equal(expected, parsed); // SVAR expected = PROTOCOL_COMMAND_VAR_SECURE; parsed = GetCommandClassic("SVAR 123"); assert_int_equal(expected, parsed); // CONTEXT expected = PROTOCOL_COMMAND_CONTEXT; parsed = GetCommandClassic("CONTEXT 123"); assert_int_equal(expected, parsed); // SCONTEXT expected = PROTOCOL_COMMAND_CONTEXT_SECURE; parsed = GetCommandClassic("SCONTEXT 123"); assert_int_equal(expected, parsed); // SQUERY expected = PROTOCOL_COMMAND_QUERY_SECURE; parsed = GetCommandClassic("SQUERY 123"); assert_int_equal(expected, parsed); // SCALLBACK expected = PROTOCOL_COMMAND_CALL_ME_BACK; parsed = GetCommandClassic("SCALLBACK 123"); assert_int_equal(expected, parsed); }