+ challenge_key = data_blob_string_const(r->in.computer_name);
+ if (pipe_state != NULL) {
+ dce_call->context->private_data = NULL;
+
+ /*
+ * If we had a challenge remembered on the connection
+ * consider this for usage. This can't be cleanup
+ * by other clients.
+ *
+ * This is the default code path for typical clients
+ * which call netr_ServerReqChallenge() and
+ * netr_ServerAuthenticate3() on the same dcerpc connection.
+ */
+ challenge = *pipe_state;
+ TALLOC_FREE(pipe_state);
+ challenge_valid = true;
+ } else {
+ DATA_BLOB val;
+ bool ok;
+
+ /*
+ * Fallback and try to get the challenge from
+ * the global cache.
+ *
+ * If too many clients are using this code path,
+ * they may destroy their cache entries as the
+ * global_challenge_table memcache has a fixed size.
+ *
+ * Note: this handles global_challenge_table == NULL fine
+ */
+ ok = memcache_lookup(global_challenge_table, SINGLETON_CACHE,
+ challenge_key, &val);
+ if (ok && val.length == sizeof(challenge)) {
+ memcpy(&challenge, val.data, sizeof(challenge));
+ challenge_valid = true;
+ } else {
+ ZERO_STRUCT(challenge);
+ }
+ }
+
+ /*
+ * At this point we can cleanup the cache entry,
+ * if we fail the client needs to call netr_ServerReqChallenge
+ * again.
+ *
+ * Note: this handles global_challenge_table == NULL
+ * and also a non existing record just fine.
+ */
+ memcache_delete(global_challenge_table,
+ SINGLETON_CACHE, challenge_key);
+