+ if (dce_conn->max_auth_states == 0) {
+ call->auth_state = dce_conn->default_auth_state;
+ } else if (call->pkt.auth_length == 0) {
+ if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
+ dce_conn->default_auth_level_connect != NULL)
+ {
+ call->auth_state = dce_conn->default_auth_level_connect;
+ } else {
+ call->auth_state = dce_conn->default_auth_state;
+ }
+ }
+
+ if (call->auth_state == NULL) {
+ struct dcesrv_auth *a = NULL;
+
+ auth_type = dcerpc_get_auth_type(&blob);
+ auth_level = dcerpc_get_auth_level(&blob);
+ auth_context_id = dcerpc_get_auth_context_id(&blob);
+
+ if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
+ dce_conn->default_auth_level_connect = NULL;
+ if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
+ dce_conn->got_explicit_auth_level_connect = true;
+ }
+ }
+
+ for (a = dce_conn->auth_states; a != NULL; a = a->next) {
+ num_auth_ctx++;
+
+ if (a->auth_type != auth_type) {
+ continue;
+ }
+ if (a->auth_finished && a->auth_level != auth_level) {
+ continue;
+ }
+ if (a->auth_context_id != auth_context_id) {
+ continue;
+ }
+
+ DLIST_PROMOTE(dce_conn->auth_states, a);
+ call->auth_state = a;
+ break;
+ }
+ }
+
+ if (call->auth_state == NULL) {
+ struct dcesrv_auth *a = NULL;
+
+ if (num_auth_ctx >= dce_conn->max_auth_states) {
+ return dcesrv_fault_disconnect(call,
+ DCERPC_NCA_S_PROTO_ERROR);
+ }
+
+ a = dcesrv_auth_create(dce_conn);
+ if (a == NULL) {
+ talloc_free(call);
+ return NT_STATUS_NO_MEMORY;
+ }
+ DLIST_ADD(dce_conn->auth_states, a);
+ if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
+ /*
+ * This can never be valid.
+ */
+ a->auth_invalid = true;
+ }
+ call->auth_state = a;
+ }