15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/restricted_token_utils.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// launcher.exe is an application used to launch another application with a
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// restricted token. This is to be used for testing only.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The parameters are the level of security of the primary token, the
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// impersonation token and the job object along with the command line to
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// execute.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See the usage (launcher.exe without parameters) for the correct format.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PARAM_IS(y) (argc > i) && (_wcsicmp(argv[i], y) == 0)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintUsage(const wchar_t *application_name) {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wprintf(L"\n\nUsage: \n  %ls --main level --init level --job level cmd_line ",
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          application_name);
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wprintf(L"\n\n  Levels : \n\tLOCKDOWN \n\tRESTRICTED "
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"\n\tLIMITED_USER \n\tINTERACTIVE_USER \n\tNON_ADMIN \n\tUNPROTECTED");
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wprintf(L"\n\n  main: Security level of the main token");
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wprintf(L"\n  init: Security level of the impersonation token");
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wprintf(L"\n  job: Security level of the job object");
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetTokenLevelFromString(const wchar_t *param,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             sandbox::TokenLevel* level) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (_wcsicmp(param, L"LOCKDOWN") == 0) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::USER_LOCKDOWN;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (_wcsicmp(param, L"RESTRICTED") == 0) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::USER_RESTRICTED;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (_wcsicmp(param, L"LIMITED_USER") == 0) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::USER_LIMITED;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (_wcsicmp(param, L"INTERACTIVE_USER") == 0) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::USER_INTERACTIVE;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (_wcsicmp(param, L"NON_ADMIN") == 0) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::USER_NON_ADMIN;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (_wcsicmp(param, L"USER_RESTRICTED_SAME_ACCESS") == 0) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::USER_RESTRICTED_SAME_ACCESS;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (_wcsicmp(param, L"UNPROTECTED") == 0) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::USER_UNPROTECTED;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetJobLevelFromString(const wchar_t *param, sandbox::JobLevel* level) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (_wcsicmp(param, L"LOCKDOWN") == 0) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::JOB_LOCKDOWN;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (_wcsicmp(param, L"RESTRICTED") == 0) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::JOB_RESTRICTED;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (_wcsicmp(param, L"LIMITED_USER") == 0) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::JOB_LIMITED_USER;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (_wcsicmp(param, L"INTERACTIVE_USER") == 0) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::JOB_INTERACTIVE;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (_wcsicmp(param, L"NON_ADMIN") == 0) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wprintf(L"\nNON_ADMIN is not a supported job type");
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (_wcsicmp(param, L"UNPROTECTED") == 0) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *level = sandbox::JOB_UNPROTECTED;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int wmain(int argc, wchar_t *argv[]) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extract the filename from the path.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t *app_name = wcsrchr(argv[0], L'\\');
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!app_name) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_name = argv[0];
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_name++;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // no argument
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (argc == 1) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintUsage(app_name);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sandbox::TokenLevel primary_level = sandbox::USER_LOCKDOWN;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sandbox::TokenLevel impersonation_level =
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sandbox::USER_RESTRICTED_SAME_ACCESS;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sandbox::JobLevel job_level = sandbox::JOB_LOCKDOWN;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ATL::CString command_line;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parse command line.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 1; i < argc; ++i) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (PARAM_IS(L"--main")) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i++;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (argc > i) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!GetTokenLevelFromString(argv[i], &primary_level)) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          wprintf(L"\nAbord, Unrecognized main token level \"%ls\"", argv[i]);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PrintUsage(app_name);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return -1;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (PARAM_IS(L"--init")) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i++;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (argc > i) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!GetTokenLevelFromString(argv[i], &impersonation_level)) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          wprintf(L"\nAbord, Unrecognized init token level \"%ls\"", argv[i]);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PrintUsage(app_name);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return -1;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (PARAM_IS(L"--job")) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i++;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (argc > i) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!GetJobLevelFromString(argv[i], &job_level)) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          wprintf(L"\nAbord, Unrecognized job security level \"%ls\"", argv[i]);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PrintUsage(app_name);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return -1;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (command_line.GetLength()) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        command_line += L' ';
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line += argv[i];
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!command_line.GetLength()) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wprintf(L"\nAbord, No command line specified");
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintUsage(app_name);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wprintf(L"\nLaunching command line: \"%ls\"\n", command_line.GetBuffer());
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE job_handle;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD err_code = sandbox::StartRestrictedProcessInJob(
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.GetBuffer(),
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      primary_level,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      impersonation_level,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      job_level,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &job_handle);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ERROR_SUCCESS != err_code) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wprintf(L"\nAbord, Error %d while launching command line.", err_code);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wprintf(L"\nPress any key to continue.");
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while(!_kbhit()) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Sleep(100);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::CloseHandle(job_handle);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
157