/* If the key and port are found return 1 otherwise return 0 */ int AVL_is_in_tree(u_long key, uint16_t port, AvlTree tree) { if (tree == NULL) { return( 0 ); } if (key < tree->key) return( AVL_is_in_tree( key, port, tree->left )); else if ( key > tree->key ) return( AVL_is_in_tree( key, port, tree->right )); else { if (port < tree->port) return( AVL_is_in_tree( key, port, tree->left ) ); else if ( port > tree->port ) return( AVL_is_in_tree( key, port, tree->right )); } return( 1 ); } /* end AVL_is_in_tree */
void process_request( int sfds) /* file descriptor (socket) to get request */ { #ifdef PBS_MOM char *id = "process_request"; #endif int rc; struct batch_request *request = NULL; #ifndef PBS_MOM char *auth_err = NULL; #endif time_now = time(NULL); request = alloc_br(0); request->rq_conn = sfds; /* * Read in the request and decode it to the internal request structure. */ #ifndef PBS_MOM if (svr_conn[sfds].cn_active == FromClientDIS) { #ifdef ENABLE_UNIX_SOCKETS if ((svr_conn[sfds].cn_socktype & PBS_SOCK_UNIX) && (svr_conn[sfds].cn_authen != PBS_NET_CONN_AUTHENTICATED)) { get_creds(sfds, conn_credent[sfds].username, conn_credent[sfds].hostname); } #endif /* END ENABLE_UNIX_SOCKETS */ rc = dis_request_read(sfds, request); } else { LOG_EVENT( PBSEVENT_SYSTEM, PBS_EVENTCLASS_REQUEST, "process_req", "request on invalid type of connection"); close_conn(sfds); free_br(request); return; } #else /* PBS_MOM */ rc = dis_request_read(sfds, request); #endif /* PBS_MOM */ if (rc == -1) { /* FAILURE */ /* premature end of file */ close_client(sfds); free_br(request); return; } if ((rc == PBSE_SYSTEM) || (rc == PBSE_INTERNAL)) { /* FAILURE */ /* read error, likely cannot send reply so just disconnect */ /* ??? not sure about this ??? */ close_client(sfds); free_br(request); return; } if (rc > 0) { /* FAILURE */ /* * request didn't decode, either garbage or unknown * request type, in either case, return reject-reply */ req_reject(rc, 0, request, NULL, "cannot decode message"); close_client(sfds); return; } if (get_connecthost(sfds, request->rq_host, PBS_MAXHOSTNAME) != 0) { char tmpLine[1024]; sprintf(log_buffer, "%s: %lu", pbse_to_txt(PBSE_BADHOST), get_connectaddr(sfds)); LOG_EVENT(PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, "", log_buffer); snprintf(tmpLine, sizeof(tmpLine), "cannot determine hostname for connection from %lu", get_connectaddr(sfds)); req_reject(PBSE_BADHOST, 0, request, NULL, tmpLine); return; } if (LOGLEVEL >= 1) { sprintf( log_buffer, msg_request, reqtype_to_txt(request->rq_type), request->rq_user, request->rq_host, sfds); LOG_EVENT(PBSEVENT_DEBUG2, PBS_EVENTCLASS_REQUEST, "", log_buffer); } /* is the request from a host acceptable to the server */ #ifndef PBS_MOM if (svr_conn[sfds].cn_socktype & PBS_SOCK_UNIX) { strcpy(request->rq_host, server_name); } if (server.sv_attr[SRV_ATR_acl_host_enable].at_val.at_long) { /* acl enabled, check it; always allow myself and nodes */ struct pbsnode *isanode; isanode = PGetNodeFromAddr(get_connectaddr(sfds)); if ((isanode == NULL) && (strcmp(server_host, request->rq_host) != 0) && (acl_check( &server.sv_attr[SRV_ATR_acl_hosts], request->rq_host, ACL_Host) == 0)) { char tmpLine[1024]; snprintf(tmpLine, sizeof(tmpLine), "request not authorized from host %s", request->rq_host); req_reject(PBSE_BADHOST, 0, request, NULL, tmpLine); close_client(sfds); return; } } /* * determine source (user client or another server) of request. * set the permissions granted to the client */ if (svr_conn[sfds].cn_authen == PBS_NET_CONN_FROM_PRIVIL) { /* request came from another server */ request->rq_fromsvr = 1; request->rq_perm = ATR_DFLAG_USRD | ATR_DFLAG_USWR | ATR_DFLAG_OPRD | ATR_DFLAG_OPWR | ATR_DFLAG_MGRD | ATR_DFLAG_MGWR | ATR_DFLAG_SvWR; } else { /* request not from another server */ request->rq_fromsvr = 0; /* * Client must be authenticated by an Authenticate User Request, if not, * reject request and close connection. -- The following is retained for * compat with old cmds -- The exception to this is of course the Connect * Request which cannot have been authenticated, because it contains the * needed ticket; so trap it here. Of course, there is no prior * authentication on the Authenticate User request either, but it comes * over a reserved port and appears from another server, hence is * automatically granted authentication. * * The above is only true with inet sockets. With unix domain sockets, the * user creds were read before the first dis_request_read call above. * We automatically granted authentication because we can trust the socket * creds. Authorization is still granted in svr_get_privilege below */ if (request->rq_type == PBS_BATCH_Connect) { req_connect(request); if (svr_conn[sfds].cn_socktype == PBS_SOCK_INET) return; } if (svr_conn[sfds].cn_socktype & PBS_SOCK_UNIX) { conn_credent[sfds].timestamp = time_now; svr_conn[sfds].cn_authen = PBS_NET_CONN_AUTHENTICATED; } if (ENABLE_TRUSTED_AUTH == TRUE ) rc = 0; /* bypass the authentication of the user--trust the client completely */ else if (munge_on) { /* If munge_on is true we will validate the connection now */ if ( request->rq_type == PBS_BATCH_AltAuthenUser) { rc = req_altauthenuser(request); if (rc == PBSE_NONE) { conn_credent[sfds].timestamp = time_now; svr_conn[sfds].cn_authen = PBS_NET_CONN_AUTHENTICATED; } return; } else if (svr_conn[sfds].cn_authen != PBS_NET_CONN_AUTHENTICATED) /* skip checking user if we did not get an authenticated credential */ rc = PBSE_BADCRED; else { rc = authenticate_user(request, &conn_credent[sfds], &auth_err); } } else if (svr_conn[sfds].cn_authen != PBS_NET_CONN_AUTHENTICATED) rc = PBSE_BADCRED; else rc = authenticate_user(request, &conn_credent[sfds], &auth_err); if (rc != 0) { req_reject(rc, 0, request, NULL, auth_err); if (auth_err != NULL) free(auth_err); close_client(sfds); return; } /* * pbs_mom and checkpoint restart scripts both need the authority to do * alters and releases on checkpointable jobs. Allow manager permission * for root on the jobs execution node. */ if (((request->rq_type == PBS_BATCH_ModifyJob) || (request->rq_type == PBS_BATCH_ReleaseJob)) && (strcmp(request->rq_user, PBS_DEFAULT_ADMIN) == 0)) { job *pjob; char *dptr; int skip = FALSE; char short_host[PBS_MAXHOSTNAME+1]; /* make short host name */ strcpy(short_host, request->rq_host); if ((dptr = strchr(short_host, '.')) != NULL) { *dptr = '\0'; } if (((pjob = find_job(request->rq_ind.rq_modify.rq_objname)) != (job *)0) && (pjob->ji_qs.ji_state == JOB_STATE_RUNNING)) { if ((pjob->ji_wattr[JOB_ATR_checkpoint].at_flags & ATR_VFLAG_SET) && ((csv_find_string(pjob->ji_wattr[JOB_ATR_checkpoint].at_val.at_str, "s") != NULL) || (csv_find_string(pjob->ji_wattr[JOB_ATR_checkpoint].at_val.at_str, "c") != NULL) || (csv_find_string(pjob->ji_wattr[JOB_ATR_checkpoint].at_val.at_str, "enabled") != NULL)) && (strstr(pjob->ji_wattr[JOB_ATR_exec_host].at_val.at_str, short_host) != NULL)) { request->rq_perm = svr_get_privilege(request->rq_user, server_host); skip = TRUE; } } if (!skip) { request->rq_perm = svr_get_privilege(request->rq_user, request->rq_host); } } else { request->rq_perm = svr_get_privilege(request->rq_user, request->rq_host); } } /* END else (svr_conn[sfds].cn_authen == PBS_NET_CONN_FROM_PRIVIL) */ /* if server shutting down, disallow new jobs and new running */ if (server.sv_attr[SRV_ATR_State].at_val.at_long > SV_STATE_RUN) { switch (request->rq_type) { case PBS_BATCH_AsyrunJob: case PBS_BATCH_JobCred: case PBS_BATCH_MoveJob: case PBS_BATCH_QueueJob: case PBS_BATCH_RunJob: case PBS_BATCH_StageIn: case PBS_BATCH_jobscript: req_reject(PBSE_SVRDOWN, 0, request, NULL, NULL); return; /*NOTREACHED*/ break; } } #else /* THIS CODE FOR MOM ONLY */ { /*extern tree *okclients; */ extern void mom_server_update_receive_time_by_ip(u_long ipaddr, const char *cmd); /* check connecting host against allowed list of ok clients */ if (LOGLEVEL >= 6) { sprintf(log_buffer, "request type %s from host %s received", reqtype_to_txt(request->rq_type), request->rq_host); log_record( PBSEVENT_JOB, PBS_EVENTCLASS_JOB, id, log_buffer); } /* if (!tfind(svr_conn[sfds].cn_addr, &okclients)) */ if (!AVL_is_in_tree(svr_conn[sfds].cn_addr, 0, okclients)) { sprintf(log_buffer, "request type %s from host %s rejected (host not authorized)", reqtype_to_txt(request->rq_type), request->rq_host); log_record( PBSEVENT_JOB, PBS_EVENTCLASS_JOB, id, log_buffer); req_reject(PBSE_BADHOST, 0, request, NULL, "request not authorized"); close_client(sfds); return; } if (LOGLEVEL >= 3) { sprintf(log_buffer, "request type %s from host %s allowed", reqtype_to_txt(request->rq_type), request->rq_host); log_record( PBSEVENT_JOB, PBS_EVENTCLASS_JOB, id, log_buffer); } mom_server_update_receive_time_by_ip(svr_conn[sfds].cn_addr, reqtype_to_txt(request->rq_type)); } /* END BLOCK */ request->rq_fromsvr = 1; request->rq_perm = ATR_DFLAG_USRD | ATR_DFLAG_USWR | ATR_DFLAG_OPRD | ATR_DFLAG_OPWR | ATR_DFLAG_MGRD | ATR_DFLAG_MGWR | ATR_DFLAG_SvWR | ATR_DFLAG_MOM; #endif /* END else !PBS_MOM */ /* * dispatch the request to the correct processing function. * The processing function must call reply_send() to free * the request struture. */ dispatch_request(sfds, request); return; } /* END process_request() */
AvlTree AVL_insert( u_long key, uint16_t port, struct pbsnode *node, AvlTree tree ) { /* If this key is already in the tree do nothing */ if (AVL_is_in_tree( key, port, tree )) { return( tree ); } if (tree == NULL) { /* Create and return a node */ if ((tree = ( AvlTree )calloc(1, sizeof( struct AvlNode ) )) == NULL) { return( tree ); } tree->key = key; tree->port = port; tree->pbsnode = node; tree->left = NULL; tree->right = NULL; tree->height = 0; } /* If key is less than current node value go left else go right. If equal compare port and go left or right accordingly */ if (key < tree->key) { tree->left = AVL_insert( key, port, node, tree->left ); if (height( tree->left ) - height( tree->right ) == 2 ) { if (key <= tree->left->key ) tree = single_rotate_with_left( tree ); else tree = double_rotate_with_left( tree ); } } else if (key > tree->key ) { tree->right = AVL_insert( key, port, node, tree->right ); if ((height( tree->right ) - height( tree->left )) == 2 ) { if (key >= tree->right->key) tree = single_rotate_with_right( tree ); else tree = double_rotate_with_right( tree ); } } else { /* the keys are equal. sort by port */ if (port != 0) { if (port < tree->port) { tree->left = AVL_insert( key, port, node, tree->left ); if (height( tree->left ) - height( tree->right ) == 2) { if (port <= tree->left->port) tree = single_rotate_with_left( tree ); else tree = double_rotate_with_left( tree ); } } else if (port > tree->port ) { tree->right = AVL_insert( key, port, node, tree->right ); if (height( tree->right ) - height( tree->left ) == 2) { if (port >= tree->right->port) tree = single_rotate_with_right( tree ); else tree = double_rotate_with_right( tree ); } } } } tree->height = Max( height( tree->left ), height( tree->right )) + 1; return( tree ); } /* End AVL_insert */