mock_gssapi_library_posix.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. // Copyright (c) 2010 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/http/mock_gssapi_library_posix.h"
  5. #include "base/strings/string_util.h"
  6. #include "base/strings/stringprintf.h"
  7. #include "testing/gtest/include/gtest/gtest.h"
  8. namespace net {
  9. namespace test {
  10. struct GssNameMockImpl {
  11. std::string name;
  12. gss_OID_desc name_type;
  13. static GssNameMockImpl* FromGssName(gss_name_t name) {
  14. return reinterpret_cast<GssNameMockImpl*>(name);
  15. }
  16. static gss_name_t ToGssName(GssNameMockImpl* name) {
  17. return reinterpret_cast<gss_name_t>(name);
  18. }
  19. };
  20. } // namespace test
  21. namespace {
  22. // gss_OID helpers.
  23. // NOTE: gss_OID's do not own the data they point to, which should be static.
  24. void ClearOid(gss_OID dest) {
  25. if (!dest)
  26. return;
  27. dest->length = 0;
  28. dest->elements = nullptr;
  29. }
  30. void SetOid(gss_OID dest, const void* src, size_t length) {
  31. if (!dest)
  32. return;
  33. ClearOid(dest);
  34. if (!src)
  35. return;
  36. dest->length = length;
  37. if (length)
  38. dest->elements = const_cast<void*>(src);
  39. }
  40. void CopyOid(gss_OID dest, const gss_OID_desc* src) {
  41. if (!dest)
  42. return;
  43. ClearOid(dest);
  44. if (!src)
  45. return;
  46. SetOid(dest, src->elements, src->length);
  47. }
  48. // gss_buffer_t helpers.
  49. void ClearBuffer(gss_buffer_t dest) {
  50. if (!dest)
  51. return;
  52. dest->length = 0;
  53. if (dest->value) {
  54. delete[] reinterpret_cast<char*>(dest->value);
  55. dest->value = nullptr;
  56. }
  57. }
  58. void SetBuffer(gss_buffer_t dest, const void* src, size_t length) {
  59. if (!dest)
  60. return;
  61. ClearBuffer(dest);
  62. if (!src)
  63. return;
  64. dest->length = length;
  65. if (length) {
  66. dest->value = new char[length];
  67. memcpy(dest->value, src, length);
  68. }
  69. }
  70. void CopyBuffer(gss_buffer_t dest, const gss_buffer_t src) {
  71. if (!dest)
  72. return;
  73. ClearBuffer(dest);
  74. if (!src)
  75. return;
  76. SetBuffer(dest, src->value, src->length);
  77. }
  78. std::string BufferToString(const gss_buffer_t src) {
  79. std::string dest;
  80. if (!src)
  81. return dest;
  82. const char* string = reinterpret_cast<char*>(src->value);
  83. dest.assign(string, src->length);
  84. return dest;
  85. }
  86. void BufferFromString(const std::string& src, gss_buffer_t dest) {
  87. if (!dest)
  88. return;
  89. SetBuffer(dest, src.c_str(), src.length());
  90. }
  91. // gss_name_t helpers.
  92. void ClearName(gss_name_t dest) {
  93. if (!dest)
  94. return;
  95. auto* name = test::GssNameMockImpl::FromGssName(dest);
  96. name->name.clear();
  97. ClearOid(&name->name_type);
  98. }
  99. void SetName(gss_name_t dest, const void* src, size_t length) {
  100. if (!dest)
  101. return;
  102. ClearName(dest);
  103. if (!src)
  104. return;
  105. auto* name = test::GssNameMockImpl::FromGssName(dest);
  106. name->name.assign(reinterpret_cast<const char*>(src), length);
  107. }
  108. gss_name_t NameFromString(const std::string& src) {
  109. gss_name_t dest = test::GssNameMockImpl::ToGssName(
  110. new test::GssNameMockImpl{"", {0, nullptr}});
  111. SetName(dest, src.c_str(), src.length());
  112. return dest;
  113. }
  114. } // namespace
  115. namespace test {
  116. GssContextMockImpl::GssContextMockImpl()
  117. : lifetime_rec(0),
  118. ctx_flags(0),
  119. locally_initiated(0),
  120. open(0) {
  121. ClearOid(&mech_type);
  122. }
  123. GssContextMockImpl::GssContextMockImpl(const GssContextMockImpl& other)
  124. : src_name(other.src_name),
  125. targ_name(other.targ_name),
  126. lifetime_rec(other.lifetime_rec),
  127. ctx_flags(other.ctx_flags),
  128. locally_initiated(other.locally_initiated),
  129. open(other.open) {
  130. CopyOid(&mech_type, &other.mech_type);
  131. }
  132. GssContextMockImpl::GssContextMockImpl(const char* src_name_in,
  133. const char* targ_name_in,
  134. OM_uint32 lifetime_rec_in,
  135. const gss_OID_desc& mech_type_in,
  136. OM_uint32 ctx_flags_in,
  137. int locally_initiated_in,
  138. int open_in)
  139. : src_name(src_name_in ? src_name_in : ""),
  140. targ_name(targ_name_in ? targ_name_in : ""),
  141. lifetime_rec(lifetime_rec_in),
  142. ctx_flags(ctx_flags_in),
  143. locally_initiated(locally_initiated_in),
  144. open(open_in) {
  145. CopyOid(&mech_type, &mech_type_in);
  146. }
  147. GssContextMockImpl::~GssContextMockImpl() {
  148. ClearOid(&mech_type);
  149. }
  150. void GssContextMockImpl::Assign(
  151. const GssContextMockImpl& other) {
  152. if (&other == this)
  153. return;
  154. src_name = other.src_name;
  155. targ_name = other.targ_name;
  156. lifetime_rec = other.lifetime_rec;
  157. CopyOid(&mech_type, &other.mech_type);
  158. ctx_flags = other.ctx_flags;
  159. locally_initiated = other.locally_initiated;
  160. open = other.open;
  161. }
  162. MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery()
  163. : expected_package(),
  164. response_code(0),
  165. minor_response_code(0),
  166. context_info() {
  167. expected_input_token.length = 0;
  168. expected_input_token.value = nullptr;
  169. output_token.length = 0;
  170. output_token.value = nullptr;
  171. }
  172. MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery(
  173. const std::string& in_expected_package,
  174. OM_uint32 in_response_code,
  175. OM_uint32 in_minor_response_code,
  176. const test::GssContextMockImpl& in_context_info,
  177. const char* in_expected_input_token,
  178. const char* in_output_token)
  179. : expected_package(in_expected_package),
  180. response_code(in_response_code),
  181. minor_response_code(in_minor_response_code),
  182. context_info(in_context_info) {
  183. if (in_expected_input_token) {
  184. expected_input_token.length = strlen(in_expected_input_token);
  185. expected_input_token.value = const_cast<char*>(in_expected_input_token);
  186. } else {
  187. expected_input_token.length = 0;
  188. expected_input_token.value = nullptr;
  189. }
  190. if (in_output_token) {
  191. output_token.length = strlen(in_output_token);
  192. output_token.value = const_cast<char*>(in_output_token);
  193. } else {
  194. output_token.length = 0;
  195. output_token.value = nullptr;
  196. }
  197. }
  198. MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery(
  199. const SecurityContextQuery& other) = default;
  200. MockGSSAPILibrary::SecurityContextQuery::~SecurityContextQuery() = default;
  201. MockGSSAPILibrary::MockGSSAPILibrary() = default;
  202. MockGSSAPILibrary::~MockGSSAPILibrary() = default;
  203. void MockGSSAPILibrary::ExpectSecurityContext(
  204. const std::string& expected_package,
  205. OM_uint32 response_code,
  206. OM_uint32 minor_response_code,
  207. const GssContextMockImpl& context_info,
  208. const gss_buffer_desc& expected_input_token,
  209. const gss_buffer_desc& output_token) {
  210. SecurityContextQuery security_query;
  211. security_query.expected_package = expected_package;
  212. security_query.response_code = response_code;
  213. security_query.minor_response_code = minor_response_code;
  214. security_query.context_info.Assign(context_info);
  215. security_query.expected_input_token = expected_input_token;
  216. security_query.output_token = output_token;
  217. expected_security_queries_.push_back(security_query);
  218. }
  219. bool MockGSSAPILibrary::Init(const NetLogWithSource&) {
  220. return true;
  221. }
  222. // These methods match the ones in the GSSAPI library.
  223. OM_uint32 MockGSSAPILibrary::import_name(
  224. OM_uint32* minor_status,
  225. const gss_buffer_t input_name_buffer,
  226. const gss_OID input_name_type,
  227. gss_name_t* output_name) {
  228. if (minor_status)
  229. *minor_status = 0;
  230. if (!output_name)
  231. return GSS_S_BAD_NAME;
  232. if (!input_name_buffer)
  233. return GSS_S_CALL_BAD_STRUCTURE;
  234. if (!input_name_type)
  235. return GSS_S_BAD_NAMETYPE;
  236. GssNameMockImpl* output = new GssNameMockImpl;
  237. if (output == nullptr)
  238. return GSS_S_FAILURE;
  239. output->name_type.length = 0;
  240. output->name_type.elements = nullptr;
  241. // Save the data.
  242. output->name = BufferToString(input_name_buffer);
  243. CopyOid(&output->name_type, input_name_type);
  244. *output_name = test::GssNameMockImpl::ToGssName(output);
  245. return GSS_S_COMPLETE;
  246. }
  247. OM_uint32 MockGSSAPILibrary::release_name(
  248. OM_uint32* minor_status,
  249. gss_name_t* input_name) {
  250. if (minor_status)
  251. *minor_status = 0;
  252. if (!input_name)
  253. return GSS_S_BAD_NAME;
  254. if (!*input_name)
  255. return GSS_S_COMPLETE;
  256. GssNameMockImpl* name = GssNameMockImpl::FromGssName(*input_name);
  257. ClearName(*input_name);
  258. delete name;
  259. *input_name = GSS_C_NO_NAME;
  260. return GSS_S_COMPLETE;
  261. }
  262. OM_uint32 MockGSSAPILibrary::release_buffer(
  263. OM_uint32* minor_status,
  264. gss_buffer_t buffer) {
  265. if (minor_status)
  266. *minor_status = 0;
  267. if (!buffer)
  268. return GSS_S_BAD_NAME;
  269. ClearBuffer(buffer);
  270. return GSS_S_COMPLETE;
  271. }
  272. OM_uint32 MockGSSAPILibrary::display_name(
  273. OM_uint32* minor_status,
  274. const gss_name_t input_name,
  275. gss_buffer_t output_name_buffer,
  276. gss_OID* output_name_type) {
  277. if (minor_status)
  278. *minor_status = 0;
  279. if (!input_name)
  280. return GSS_S_BAD_NAME;
  281. if (!output_name_buffer)
  282. return GSS_S_CALL_BAD_STRUCTURE;
  283. if (!output_name_type)
  284. return GSS_S_CALL_BAD_STRUCTURE;
  285. GssNameMockImpl* internal_name = GssNameMockImpl::FromGssName(input_name);
  286. std::string name = internal_name->name;
  287. BufferFromString(name, output_name_buffer);
  288. if (output_name_type) {
  289. *output_name_type =
  290. internal_name ? &internal_name->name_type : GSS_C_NO_OID;
  291. }
  292. return GSS_S_COMPLETE;
  293. }
  294. OM_uint32 MockGSSAPILibrary::display_status(
  295. OM_uint32* minor_status,
  296. OM_uint32 status_value,
  297. int status_type,
  298. const gss_OID mech_type,
  299. OM_uint32* message_context,
  300. gss_buffer_t status_string) {
  301. OM_uint32 rv = GSS_S_COMPLETE;
  302. *minor_status = 0;
  303. std::string msg;
  304. switch (static_cast<DisplayStatusSpecials>(status_value)) {
  305. case DisplayStatusSpecials::MultiLine:
  306. msg = base::StringPrintf("Line %u for status %u", ++*message_context,
  307. status_value);
  308. if (*message_context >= 5u)
  309. *message_context = 0u;
  310. break;
  311. case DisplayStatusSpecials::InfiniteLines:
  312. msg = base::StringPrintf("Line %u for status %u", ++*message_context,
  313. status_value);
  314. break;
  315. case DisplayStatusSpecials::Fail:
  316. rv = GSS_S_BAD_MECH;
  317. msg = "You should not see this";
  318. EXPECT_EQ(*message_context, 0u);
  319. break;
  320. case DisplayStatusSpecials::EmptyMessage:
  321. EXPECT_EQ(*message_context, 0u);
  322. break;
  323. case DisplayStatusSpecials::UninitalizedBuffer:
  324. EXPECT_EQ(*message_context, 0u);
  325. return GSS_S_COMPLETE;
  326. case DisplayStatusSpecials::InvalidUtf8:
  327. msg = "\xff\xff\xff";
  328. EXPECT_EQ(*message_context, 0u);
  329. break;
  330. default:
  331. msg = base::StringPrintf("Value: %u, Type %u", status_value, status_type);
  332. EXPECT_EQ(*message_context, 0u);
  333. }
  334. BufferFromString(msg, status_string);
  335. return rv;
  336. }
  337. OM_uint32 MockGSSAPILibrary::init_sec_context(
  338. OM_uint32* minor_status,
  339. const gss_cred_id_t initiator_cred_handle,
  340. gss_ctx_id_t* context_handle,
  341. const gss_name_t target_name,
  342. const gss_OID mech_type,
  343. OM_uint32 req_flags,
  344. OM_uint32 time_req,
  345. const gss_channel_bindings_t input_chan_bindings,
  346. const gss_buffer_t input_token,
  347. gss_OID* actual_mech_type,
  348. gss_buffer_t output_token,
  349. OM_uint32* ret_flags,
  350. OM_uint32* time_rec) {
  351. if (minor_status)
  352. *minor_status = 0;
  353. if (!context_handle)
  354. return GSS_S_CALL_BAD_STRUCTURE;
  355. GssContextMockImpl** internal_context_handle =
  356. reinterpret_cast<test::GssContextMockImpl**>(context_handle);
  357. // Create it if necessary.
  358. if (!*internal_context_handle) {
  359. *internal_context_handle = new GssContextMockImpl;
  360. }
  361. EXPECT_TRUE(*internal_context_handle);
  362. GssContextMockImpl& context = **internal_context_handle;
  363. if (expected_security_queries_.empty()) {
  364. return GSS_S_UNAVAILABLE;
  365. }
  366. SecurityContextQuery security_query = expected_security_queries_.front();
  367. expected_security_queries_.pop_front();
  368. EXPECT_EQ(std::string("Negotiate"), security_query.expected_package);
  369. OM_uint32 major_status = security_query.response_code;
  370. if (minor_status)
  371. *minor_status = security_query.minor_response_code;
  372. context.src_name = security_query.context_info.src_name;
  373. context.targ_name = security_query.context_info.targ_name;
  374. context.lifetime_rec = security_query.context_info.lifetime_rec;
  375. CopyOid(&context.mech_type, &security_query.context_info.mech_type);
  376. context.ctx_flags = security_query.context_info.ctx_flags;
  377. context.locally_initiated = security_query.context_info.locally_initiated;
  378. context.open = security_query.context_info.open;
  379. if (!input_token) {
  380. EXPECT_FALSE(security_query.expected_input_token.length);
  381. } else {
  382. EXPECT_EQ(input_token->length, security_query.expected_input_token.length);
  383. if (input_token->length) {
  384. EXPECT_EQ(0, memcmp(input_token->value,
  385. security_query.expected_input_token.value,
  386. input_token->length));
  387. }
  388. }
  389. CopyBuffer(output_token, &security_query.output_token);
  390. if (actual_mech_type)
  391. CopyOid(*actual_mech_type, mech_type);
  392. if (ret_flags)
  393. *ret_flags = req_flags;
  394. return major_status;
  395. }
  396. OM_uint32 MockGSSAPILibrary::wrap_size_limit(
  397. OM_uint32* minor_status,
  398. const gss_ctx_id_t context_handle,
  399. int conf_req_flag,
  400. gss_qop_t qop_req,
  401. OM_uint32 req_output_size,
  402. OM_uint32* max_input_size) {
  403. if (minor_status)
  404. *minor_status = 0;
  405. ADD_FAILURE();
  406. return GSS_S_UNAVAILABLE;
  407. }
  408. OM_uint32 MockGSSAPILibrary::delete_sec_context(
  409. OM_uint32* minor_status,
  410. gss_ctx_id_t* context_handle,
  411. gss_buffer_t output_token) {
  412. if (minor_status)
  413. *minor_status = 0;
  414. if (!context_handle)
  415. return GSS_S_CALL_BAD_STRUCTURE;
  416. GssContextMockImpl** internal_context_handle =
  417. reinterpret_cast<GssContextMockImpl**>(context_handle);
  418. if (*internal_context_handle) {
  419. delete *internal_context_handle;
  420. *internal_context_handle = nullptr;
  421. }
  422. return GSS_S_COMPLETE;
  423. }
  424. OM_uint32 MockGSSAPILibrary::inquire_context(
  425. OM_uint32* minor_status,
  426. const gss_ctx_id_t context_handle,
  427. gss_name_t* src_name,
  428. gss_name_t* targ_name,
  429. OM_uint32* lifetime_rec,
  430. gss_OID* mech_type,
  431. OM_uint32* ctx_flags,
  432. int* locally_initiated,
  433. int* open) {
  434. if (minor_status)
  435. *minor_status = 0;
  436. if (!context_handle)
  437. return GSS_S_CALL_BAD_STRUCTURE;
  438. GssContextMockImpl* internal_context_ptr =
  439. reinterpret_cast<GssContextMockImpl*>(context_handle);
  440. GssContextMockImpl& context = *internal_context_ptr;
  441. if (src_name)
  442. *src_name = NameFromString(context.src_name);
  443. if (targ_name)
  444. *targ_name = NameFromString(context.targ_name);
  445. if (lifetime_rec)
  446. *lifetime_rec = context.lifetime_rec;
  447. if (mech_type)
  448. CopyOid(*mech_type, &context.mech_type);
  449. if (ctx_flags)
  450. *ctx_flags = context.ctx_flags;
  451. if (locally_initiated)
  452. *locally_initiated = context.locally_initiated;
  453. if (open)
  454. *open = context.open;
  455. return GSS_S_COMPLETE;
  456. }
  457. const std::string& MockGSSAPILibrary::GetLibraryNameForTesting() {
  458. return library_name_;
  459. }
  460. } // namespace test
  461. } // namespace net