void req_reject( int code, /* I */ int aux, /* I */ struct batch_request *preq, /* I */ char *HostName, /* I (optional) */ char *Msg) /* I (optional) */ { char msgbuf[ERR_MSG_SIZE + 256 + 1]; char msgbuf2[ERR_MSG_SIZE + 256 + 1]; set_err_msg(code, msgbuf); snprintf(msgbuf2, sizeof(msgbuf2), "%s", msgbuf); if ((HostName != NULL) && (*HostName != '\0')) { snprintf(msgbuf, sizeof(msgbuf), "%s REJHOST=%s", msgbuf2, HostName); snprintf(msgbuf2, sizeof(msgbuf2), "%s", msgbuf); } if ((Msg != NULL) && (*Msg != '\0')) { snprintf(msgbuf, sizeof(msgbuf), "%s MSG=%s", msgbuf2, Msg); /* NOTE: Don't need this last snprintf() unless another message is concatenated. */ } sprintf(log_buffer, "Reject reply code=%d(%s), aux=%d, type=%s, from %s@%s", code, msgbuf, aux, reqtype_to_txt(preq->rq_type), preq->rq_user, preq->rq_host); LOG_EVENT( PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, "req_reject", log_buffer); preq->rq_reply.brp_auxcode = aux; reply_text(preq, code, msgbuf); return; } /* END req_reject() */
int reply_send_svr( struct batch_request *request) /* I (freed) */ { int rc = 0; char log_buf[LOCAL_LOG_BUF_SIZE]; int sfds = request->rq_conn; /* socket */ /* Handle remote replies - local batch requests no longer create work tasks */ if (sfds >= 0) { /* Otherwise, the reply is to be sent to a remote client */ if (request->rq_noreply != TRUE) { rc = dis_reply_write(sfds, &request->rq_reply); if (LOGLEVEL >= 7) { sprintf(log_buf, "Reply sent for request type %s on socket %d", reqtype_to_txt(request->rq_type), sfds); log_record(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, __func__, log_buf); } } } if (((request->rq_type != PBS_BATCH_AsyModifyJob) && (request->rq_type != PBS_BATCH_AsyrunJob) && (request->rq_type != PBS_BATCH_AsySignalJob)) || (request->rq_noreply == TRUE)) { free_br(request); } return(rc); } /* END reply_send_svr() */
int reply_send( struct batch_request *request) /* I (freed) */ { int rc = 0; int sfds = request->rq_conn; /* socket */ #ifndef PBS_MOM static char *id = "reply_send"; struct work_task *ptask; #endif /* PBS_MOM */ /* determine where the reply should go, remote or local */ if (sfds == PBS_LOCAL_CONNECTION) { #ifndef PBS_MOM /* * reply stays local, find work task and move it to * the immediate list for dispatching. */ ptask = (struct work_task *)GET_NEXT(task_list_event); while (ptask != NULL) { if ((ptask->wt_type == WORK_Deferred_Local) && (ptask->wt_parm1 == (void *)request)) { delete_link(&ptask->wt_linkall); append_link(&task_list_immed, &ptask->wt_linkall, ptask); return(0); } ptask = (struct work_task *)GET_NEXT(ptask->wt_linkall); } /* should have found a task and didn't */ log_err(-1, id, "did not find work task for local request"); #endif /* PBS_MOM */ rc = PBSE_SYSTEM; } else if (sfds >= 0) { /* Otherwise, the reply is to be sent to a remote client */ #ifndef PBS_MOM if (request->rq_noreply != TRUE) { #endif rc = dis_reply_write(sfds, &request->rq_reply); #ifndef PBS_MOM if (LOGLEVEL >= 7) { sprintf(log_buffer, "Reply sent for request type %s on socket %d", reqtype_to_txt(request->rq_type), sfds); log_record( PBSEVENT_JOB, PBS_EVENTCLASS_JOB, id, log_buffer); } #ifndef PBS_MOM } #endif #endif } #ifndef PBS_MOM if ((request->rq_type != PBS_BATCH_AsyModifyJob) || (request->rq_noreply == TRUE)) { #endif free_br(request); #ifndef PBS_MOM } #endif return(rc); } /* END reply_send() */
int process_request( struct tcp_chan *chan) /* file descriptor (socket) to get request */ { int rc = PBSE_NONE; struct batch_request *request = NULL; char log_buf[LOCAL_LOG_BUF_SIZE]; long acl_enable = FALSE; long state = SV_STATE_DOWN; time_t time_now = time(NULL); int free_request = TRUE; char tmpLine[MAXLINE]; char *auth_err = NULL; enum conn_type conn_active; unsigned short conn_socktype; unsigned short conn_authen; unsigned long conn_addr; int sfds = chan->sock; pthread_mutex_lock(svr_conn[sfds].cn_mutex); conn_active = svr_conn[sfds].cn_active; conn_socktype = svr_conn[sfds].cn_socktype; conn_authen = svr_conn[sfds].cn_authen; conn_addr = svr_conn[sfds].cn_addr; svr_conn[sfds].cn_lasttime = time_now; pthread_mutex_unlock(svr_conn[sfds].cn_mutex); if ((request = alloc_br(0)) == NULL) { snprintf(tmpLine, sizeof(tmpLine), "cannot allocate memory for request from %lu", conn_addr); req_reject(PBSE_MEM_MALLOC, 0, request, NULL, tmpLine); free_request = FALSE; rc = PBSE_SYSTEM; goto process_request_cleanup; } request->rq_conn = sfds; /* * Read in the request and decode it to the internal request structure. */ if (conn_active == FromClientDIS || conn_active == ToServerDIS) { #ifdef ENABLE_UNIX_SOCKETS if ((conn_socktype & PBS_SOCK_UNIX) && (conn_authen != PBS_NET_CONN_AUTHENTICATED)) { /* get_creds interestingly always returns 0 */ get_creds(sfds, conn_credent[sfds].username, conn_credent[sfds].hostname); } #endif /* END ENABLE_UNIX_SOCKETS */ rc = dis_request_read(chan, request); } else { char out[80]; snprintf(tmpLine, MAXLINE, "request on invalid type of connection: %d, sock type: %d, from address %s", conn_active,conn_socktype, netaddr_long(conn_addr, out)); log_event(PBSEVENT_SYSTEM, PBS_EVENTCLASS_REQUEST, "process_req", tmpLine); snprintf(tmpLine, sizeof(tmpLine), "request on invalid type of connection (%d) from %s", conn_active, netaddr_long(conn_addr, out)); req_reject(PBSE_BADHOST, 0, request, NULL, tmpLine); free_request = FALSE; rc = PBSE_BADHOST; goto process_request_cleanup; } if (rc == -1) { /* FAILURE */ /* premature end of file */ rc = PBSE_PREMATURE_EOF; goto process_request_cleanup; } if ((rc == PBSE_SYSTEM) || (rc == PBSE_INTERNAL) || (rc == PBSE_SOCKET_CLOSE)) { /* FAILURE */ /* read error, likely cannot send reply so just disconnect */ /* ??? not sure about this ??? */ goto process_request_cleanup; } 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"); free_request = FALSE; goto process_request_cleanup; } if (get_connecthost(sfds, request->rq_host, PBS_MAXHOSTNAME) != 0) { sprintf(log_buf, "%s: %lu", pbse_to_txt(PBSE_BADHOST), conn_addr); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, "", log_buf); snprintf(tmpLine, sizeof(tmpLine), "cannot determine hostname for connection from %lu", conn_addr); req_reject(PBSE_BADHOST, 0, request, NULL, tmpLine); free_request = FALSE; rc = PBSE_BADHOST; goto process_request_cleanup; } if (LOGLEVEL >= 1) { sprintf(log_buf, msg_request, reqtype_to_txt(request->rq_type), request->rq_user, request->rq_host, sfds); log_event(PBSEVENT_DEBUG2, PBS_EVENTCLASS_REQUEST, "", log_buf); } /* is the request from a host acceptable to the server */ if (conn_socktype & PBS_SOCK_UNIX) { strcpy(request->rq_host, server_name); } get_svr_attr_l(SRV_ATR_acl_host_enable, &acl_enable); if (acl_enable) { /* acl enabled, check it; always allow myself and nodes */ struct array_strings *pas = NULL; struct pbsnode *isanode; get_svr_attr_arst(SRV_ATR_acl_hosts, &pas); isanode = PGetNodeFromAddr(conn_addr); if ((isanode == NULL) && (strcmp(server_host, request->rq_host) != 0) && (acl_check_my_array_string(pas, request->rq_host, ACL_Host) == 0)) { char tmpLine[MAXLINE]; snprintf(tmpLine, sizeof(tmpLine), "request not authorized from host %s", request->rq_host); req_reject(PBSE_BADHOST, 0, request, NULL, tmpLine); free_request = FALSE; rc = PBSE_BADHOST; goto process_request_cleanup; } if (isanode != NULL) unlock_node(isanode, "process_request", NULL, LOGLEVEL); } /* * determine source (user client or another server) of request. * set the permissions granted to the client */ if (conn_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 */ conn_credent[sfds].timestamp = time_now; 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 (conn_socktype == PBS_SOCK_INET) { rc = PBSE_IVALREQ; req_reject(rc, 0, request, NULL, NULL); free_request = FALSE; goto process_request_cleanup; } } if (conn_socktype & PBS_SOCK_UNIX) { pthread_mutex_lock(svr_conn[sfds].cn_mutex); svr_conn[sfds].cn_authen = PBS_NET_CONN_AUTHENTICATED; pthread_mutex_unlock(svr_conn[sfds].cn_mutex); } if (ENABLE_TRUSTED_AUTH == TRUE ) rc = PBSE_NONE; /* 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); free_request = FALSE; goto process_request_cleanup; } else { rc = authenticate_user(request, &conn_credent[sfds], &auth_err); } } else if (conn_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); if (rc != 0) { req_reject(rc, 0, request, NULL, auth_err); if (auth_err != NULL) free(auth_err); free_request = FALSE; goto process_request_cleanup; } /* * 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 = svr_find_job(request->rq_ind.rq_modify.rq_objname, FALSE)) != (job *)0) { if (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; } } unlock_ji_mutex(pjob, __func__, "1", LOGLEVEL); } 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 (conn_authen == PBS_NET_CONN_FROM_PRIVIL) */ /* if server shutting down, disallow new jobs and new running */ get_svr_attr_l(SRV_ATR_State, &state); if (state > 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); rc = PBSE_SVRDOWN; free_request = FALSE; goto process_request_cleanup; /*NOTREACHED*/ break; } } /* * dispatch the request to the correct processing function. * The processing function must call reply_send() to free * the request struture. */ rc = dispatch_request(sfds, request); return(rc); process_request_cleanup: if (free_request == TRUE) free_br(request); return(rc); } /* END process_request() */
int dispatch_request( int sfds, /* I */ struct batch_request *request) /* I */ { int rc = PBSE_NONE; char log_buf[LOCAL_LOG_BUF_SIZE]; char *job_id = NULL; if (LOGLEVEL >= 5) { sprintf(log_buf,"dispatching request %s on sd=%d", reqtype_to_txt(request->rq_type), sfds); log_record(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, __func__, log_buf); } switch (request->rq_type) { case PBS_BATCH_QueueJob: rc = req_quejob(request, &job_id); if ((rc != PBSE_NONE) && (job_id != NULL)) close_quejob_by_jobid(job_id); if (job_id != NULL) free(job_id); break; case PBS_BATCH_JobCred: rc = req_jobcredential(request); break; case PBS_BATCH_jobscript: job_id = strdup(request->rq_ind.rq_jobfile.rq_jobid); rc = req_jobscript(request); if ((rc != PBSE_NONE) && (job_id != NULL)) close_quejob_by_jobid(job_id); if (job_id != NULL) free(job_id); break; case PBS_BATCH_RdytoCommit: job_id = strdup(request->rq_ind.rq_rdytocommit); rc = req_rdytocommit(request); if ((rc != PBSE_NONE) && (job_id != NULL)) close_quejob_by_jobid(job_id); if (job_id != NULL) free(job_id); break; case PBS_BATCH_Commit: job_id = strdup(request->rq_ind.rq_commit); rc = req_commit(request); if ((rc != PBSE_NONE) && (job_id != NULL)) close_quejob_by_jobid(job_id); if (job_id != NULL) free(job_id); break; case PBS_BATCH_DeleteJob: /* if this is a server size job delete request, then the request * could also be for an entire array. we check to see if the * request object name is an array id. If so we hand off the the * req_deletearray() function. If not we pass along to the normal * req_deletejob() function. */ if (is_array(request->rq_ind.rq_delete.rq_objname)) rc = req_deletearray(request); else rc = req_deletejob(request); break; case PBS_BATCH_HoldJob: if (is_array(request->rq_ind.rq_hold.rq_orig.rq_objname)) rc = req_holdarray(request); else rc = req_holdjob(request); break; case PBS_BATCH_CheckpointJob: rc = req_checkpointjob(request); break; case PBS_BATCH_LocateJob: rc = req_locatejob(request); break; case PBS_BATCH_Manager: rc = req_manager(request); break; case PBS_BATCH_MessJob: rc = req_messagejob(request); break; case PBS_BATCH_AsyModifyJob: case PBS_BATCH_ModifyJob: if (is_array(request->rq_ind.rq_delete.rq_objname)) rc = req_modifyarray(request); else req_modifyjob(request); break; case PBS_BATCH_Rerun: rc = req_rerunjob(request); break; case PBS_BATCH_MoveJob: rc = req_movejob(request); break; case PBS_BATCH_OrderJob: rc = req_orderjob(request); break; case PBS_BATCH_Rescq: rc = req_rescq(request); break; case PBS_BATCH_ReserveResc: rc = req_rescreserve(request); break; case PBS_BATCH_ReleaseResc: rc = req_rescfree(request); break; case PBS_BATCH_ReleaseJob: if (is_array(request->rq_ind.rq_delete.rq_objname)) rc = req_releasearray(request); else rc = req_releasejob(request); break; case PBS_BATCH_RunJob: case PBS_BATCH_AsyrunJob: globalset_del_sock(request->rq_conn); rc = req_runjob(request); break; case PBS_BATCH_SelectJobs: case PBS_BATCH_SelStat: /* handle special 'truncated' keyword */ if (!strncasecmp(request->rq_ind.rq_status.rq_id, "truncated", strlen("truncated"))) rc =req_stat_job(request); else rc = req_selectjobs(request); break; case PBS_BATCH_Shutdown: req_shutdown(request); break; case PBS_BATCH_SignalJob: case PBS_BATCH_AsySignalJob: rc = req_signaljob(request); break; case PBS_BATCH_GpuCtrl: rc = req_gpuctrl_svr(request); break; case PBS_BATCH_MvJobFile: rc = req_mvjobfile(request); break; case PBS_BATCH_StatusQue: rc = req_stat_que(request); break; case PBS_BATCH_StatusNode: rc = req_stat_node(request); break; case PBS_BATCH_StatusSvr: rc = req_stat_svr(request); break; /* DIAGTODO: handle PBS_BATCH_StatusDiag and define req_stat_diag() */ case PBS_BATCH_TrackJob: rc = req_track(request); break; case PBS_BATCH_RegistDep: if (is_array(request->rq_ind.rq_register.rq_parent)) { rc = req_registerarray(request); } else { rc = req_register(request); } break; case PBS_BATCH_AuthenUser: /* determine if user is valid */ rc = req_authenuser( request); break; case PBS_BATCH_AltAuthenUser: break; case PBS_BATCH_JobObit: rc = req_jobobit(request); break; case PBS_BATCH_StageIn: rc = req_stagein(request); break; case PBS_BATCH_StatusJob: rc = req_stat_job(request); break; default: req_reject(PBSE_UNKREQ, 0, request, NULL, NULL); if (sfds != PBS_LOCAL_CONNECTION) close_conn(sfds, FALSE); break; } /* END switch (request->rq_type) */ return(rc); } /* END dispatch_request() */
void dispatch_request( int sfds, /* I */ struct batch_request *request) /* I */ { char *id = "dispatch_request"; if (LOGLEVEL >= 5) { sprintf(log_buffer,"dispatching request %s on sd=%d", reqtype_to_txt(request->rq_type), sfds); log_record( PBSEVENT_JOB, PBS_EVENTCLASS_JOB, id, log_buffer); } switch (request->rq_type) { case PBS_BATCH_QueueJob: net_add_close_func(sfds, close_quejob); req_quejob(request); break; case PBS_BATCH_JobCred: req_jobcredential(request); break; case PBS_BATCH_jobscript: req_jobscript(request); break; case PBS_BATCH_RdytoCommit: req_rdytocommit(request); break; case PBS_BATCH_Commit: req_commit(request); net_add_close_func(sfds, (void (*)())0); break; case PBS_BATCH_DeleteJob: #ifdef PBS_MOM req_deletejob(request); #else /* if this is a server size job delete request, then the request could also be * for an entire array. we check to see if the request object name is an array id. * if so we hand off the the req_deletearray() function. If not we pass along to the * normal req_deltejob() function. */ if (is_array(request->rq_ind.rq_delete.rq_objname)) { req_deletearray(request); } else { req_deletejob(request); } #endif break; case PBS_BATCH_HoldJob: #ifdef PBS_MOM req_holdjob(request); #else if (is_array(request->rq_ind.rq_hold.rq_orig.rq_objname)) { req_holdarray(request); } else { req_holdjob(request); } #endif break; case PBS_BATCH_CheckpointJob: req_checkpointjob(request); break; #ifndef PBS_MOM case PBS_BATCH_LocateJob: req_locatejob(request); break; case PBS_BATCH_Manager: req_manager(request); break; #endif /* END !PBS_MOM */ case PBS_BATCH_MessJob: req_messagejob(request); break; case PBS_BATCH_AsyModifyJob: case PBS_BATCH_ModifyJob: #ifndef PBS_MOM if (is_array(request->rq_ind.rq_delete.rq_objname)) { req_modifyarray(request); } else { req_modifyjob(request); } #else /* END ifndef PBS_MOM */ req_modifyjob(request); #endif /* PBS_MOM */ break; case PBS_BATCH_Rerun: req_rerunjob(request); break; #ifndef PBS_MOM case PBS_BATCH_MoveJob: req_movejob(request); break; case PBS_BATCH_OrderJob: req_orderjob(request); break; case PBS_BATCH_Rescq: req_rescq(request); break; case PBS_BATCH_ReserveResc: req_rescreserve(request); break; case PBS_BATCH_ReleaseResc: req_rescfree(request); break; case PBS_BATCH_ReleaseJob: if (is_array(request->rq_ind.rq_delete.rq_objname)) { req_releasearray(request); } else { req_releasejob(request); } break; case PBS_BATCH_RunJob: case PBS_BATCH_AsyrunJob: req_runjob(request); break; case PBS_BATCH_SelectJobs: case PBS_BATCH_SelStat: /* handle special 'truncated' keyword */ if (!strncasecmp(request->rq_ind.rq_status.rq_id, "truncated", strlen("truncated"))) req_stat_job(request); else req_selectjobs(request); break; #endif /* !PBS_MOM */ case PBS_BATCH_Shutdown: req_shutdown(request); break; case PBS_BATCH_SignalJob: case PBS_BATCH_AsySignalJob: req_signaljob(request); break; case PBS_BATCH_GpuCtrl: req_gpuctrl(request); break; case PBS_BATCH_StatusJob: req_stat_job(request); break; case PBS_BATCH_MvJobFile: req_mvjobfile(request); break; #ifndef PBS_MOM /* server only functions */ case PBS_BATCH_StatusQue: req_stat_que(request); break; case PBS_BATCH_StatusNode: req_stat_node(request); break; case PBS_BATCH_StatusSvr: req_stat_svr(request); break; /* DIAGTODO: handle PBS_BATCH_StatusDiag and define req_stat_diag() */ case PBS_BATCH_TrackJob: req_track(request); break; case PBS_BATCH_RegistDep: if (is_array(request->rq_ind.rq_register.rq_parent)) { req_registerarray(request); } else { req_register(request); } break; case PBS_BATCH_AuthenUser: /* determine if user is valid */ req_authenuser(request); break; case PBS_BATCH_AltAuthenUser: break; case PBS_BATCH_JobObit: req_jobobit(request); break; case PBS_BATCH_StageIn: req_stagein(request); break; #else /* MOM only functions */ case PBS_BATCH_ReturnFiles: req_returnfiles(request); break; case PBS_BATCH_CopyFiles: req_cpyfile(request); break; case PBS_BATCH_DelFiles: req_delfile(request); break; #endif /* !PBS_MOM */ default: req_reject(PBSE_UNKREQ, 0, request, NULL, NULL); close_client(sfds); break; } /* END switch (request->rq_type) */ return; } /* END dispatch_request() */
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() */
void mom_dispatch_request( int sfds, /* I */ struct batch_request *request) /* I */ { if (LOGLEVEL >= 5) { sprintf(log_buffer,"dispatching request %s on sd=%d", reqtype_to_txt(request->rq_type), sfds); log_record(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, __func__, log_buffer); } switch (request->rq_type) { case PBS_BATCH_QueueJob: net_add_close_func(sfds, close_quejob); req_quejob(request); break; case PBS_BATCH_JobCred: req_jobcredential(request); break; case PBS_BATCH_jobscript: req_jobscript(request); break; case PBS_BATCH_RdytoCommit: req_rdytocommit(request); break; case PBS_BATCH_Commit: req_commit(request); net_add_close_func(sfds, NULL); break; case PBS_BATCH_DeleteJob: req_deletejob(request); break; case PBS_BATCH_HoldJob: mom_req_holdjob(request); break; case PBS_BATCH_CheckpointJob: req_checkpointjob(request); break; case PBS_BATCH_MessJob: req_messagejob(request); break; case PBS_BATCH_AsyModifyJob: case PBS_BATCH_ModifyJob: req_modifyjob(request); break; case PBS_BATCH_Rerun: req_rerunjob(request); break; case PBS_BATCH_Shutdown: req_shutdown(request); break; case PBS_BATCH_SignalJob: case PBS_BATCH_AsySignalJob: req_signaljob(request); break; case PBS_BATCH_MvJobFile: req_mvjobfile(request); break; case PBS_BATCH_StatusJob: req_stat_job(request); break; case PBS_BATCH_ReturnFiles: req_returnfiles(request); break; case PBS_BATCH_CopyFiles: req_cpyfile(request); break; case PBS_BATCH_DelFiles: req_delfile(request); break; case PBS_BATCH_DeleteReservation: req_delete_reservation(request); break; default: req_reject(PBSE_UNKREQ, 0, request, NULL, NULL); mom_close_client(sfds); break; } /* END switch (request->rq_type) */ return; } /* END dispatch_request() */
void *mom_process_request( void *sock_num) /* file descriptor (socket) to get request */ { int rc; struct batch_request *request = NULL; int sfds = *(int *)sock_num; struct tcp_chan *chan = NULL; time_now = time(NULL); if ((request = alloc_br(0)) == NULL) { mom_close_client(sfds); return NULL; } request->rq_conn = sfds; if ((chan = DIS_tcp_setup(sfds)) == NULL) { mom_close_client(sfds); free_br(request); return NULL; } /* Read in the request and decode it to the internal request structure. */ rc = dis_request_read(chan, request); if (rc == -1) { /* FAILURE */ /* premature end of file */ mom_close_client(chan->sock); free_br(request); DIS_tcp_cleanup(chan); return NULL; } if ((rc == PBSE_SYSTEM) || (rc == PBSE_INTERNAL) || (rc == PBSE_SOCKET_CLOSE)) { /* FAILURE */ /* read error, likely cannot send reply so just disconnect */ /* ??? not sure about this ??? */ mom_close_client(chan->sock); free_br(request); DIS_tcp_cleanup(chan); return NULL; } 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"); mom_close_client(chan->sock); DIS_tcp_cleanup(chan); return NULL; } if (get_connecthost(chan->sock, request->rq_host, PBS_MAXHOSTNAME) != 0) { char tmpLine[MAXLINE]; sprintf(log_buffer, "%s: %lu", pbse_to_txt(PBSE_BADHOST), get_connectaddr(chan->sock,FALSE)); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, "", log_buffer); snprintf(tmpLine, sizeof(tmpLine), "cannot determine hostname for connection from %lu", get_connectaddr(chan->sock,FALSE)); req_reject(PBSE_BADHOST, 0, request, NULL, tmpLine); mom_close_client(chan->sock); DIS_tcp_cleanup(chan); return NULL; } if (LOGLEVEL >= 1) { sprintf( log_buffer, msg_request, reqtype_to_txt(request->rq_type), request->rq_user, request->rq_host, chan->sock); log_event(PBSEVENT_DEBUG2, PBS_EVENTCLASS_REQUEST, "", log_buffer); } /* is the request from a host acceptable to the server */ { /*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, __func__, log_buffer); } if (!AVL_is_in_tree_no_port_compare(svr_conn[chan->sock].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, __func__, log_buffer); req_reject(PBSE_BADHOST, 0, request, NULL, "request not authorized"); mom_close_client(chan->sock); DIS_tcp_cleanup(chan); return NULL; } 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, __func__, log_buffer); } mom_server_update_receive_time_by_ip(svr_conn[chan->sock].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; /* * dispatch the request to the correct processing function. * The processing function must call reply_send() to free * the request struture. */ mom_dispatch_request(chan->sock, request); DIS_tcp_cleanup(chan); return NULL; } /* END mom_process_request() */
int dis_request_read( struct tcp_chan *chan, struct batch_request *request) /* server internal structure */ { int proto_type; int proto_ver; int rc; /* return code */ char log_buf[LOCAL_LOG_BUF_SIZE]; #ifdef PBS_MOM /* NYI: talk to Ken about this. This is necessary due to the changes to * decode_DIS_ReqHdr */ proto_type = disrui(chan, &rc); #endif /* Decode the Request Header, that will tell the request type */ if ((rc = decode_DIS_ReqHdr(chan, request, &proto_type, &proto_ver))) { if (rc == DIS_EOF) { return(EOF); } sprintf(log_buf, "req header bad, dis error %d (%s), type=%s", rc, dis_emsg[rc], reqtype_to_txt(request->rq_type)); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, __func__, log_buf); return(PBSE_DISPROTO); } if (proto_ver != PBS_BATCH_PROT_VER) { sprintf(log_buf, "conflicting version numbers, %d detected, %d expected", proto_ver, PBS_BATCH_PROT_VER); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, __func__, log_buf); return(PBSE_DISPROTO); } if ((request->rq_type < 0) || (request->rq_type >= PBS_BATCH_CEILING)) { sprintf(log_buf, "invalid request type: %d", request->rq_type); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, __func__, log_buf); return(PBSE_DISPROTO); } /* Decode the Request Body based on the type */ if (LOGLEVEL >= 5) { sprintf(log_buf, "decoding command %s from %s", reqtype_to_txt(request->rq_type), request->rq_user); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, __func__, log_buf); } switch (request->rq_type) { case PBS_BATCH_Disconnect: return(PBSE_SOCKET_CLOSE); /* set EOF return */ /*NOTREACHED*/ break; case PBS_BATCH_QueueJob: CLEAR_HEAD(request->rq_ind.rq_queuejob.rq_attr); rc = decode_DIS_QueueJob(chan, request); break; case PBS_BATCH_JobCred: rc = decode_DIS_JobCred(chan, request); break; case PBS_BATCH_jobscript: case PBS_BATCH_MvJobFile: rc = decode_DIS_JobFile(chan, request); break; case PBS_BATCH_RdytoCommit: case PBS_BATCH_Commit: case PBS_BATCH_Rerun: rc = decode_DIS_JobId(chan, request->rq_ind.rq_commit); break; case PBS_BATCH_DeleteJob: case PBS_BATCH_HoldJob: case PBS_BATCH_CheckpointJob: case PBS_BATCH_ModifyJob: case PBS_BATCH_AsyModifyJob: rc = decode_DIS_Manage(chan, request); break; case PBS_BATCH_MessJob: rc = decode_DIS_MessageJob(chan, request); break; case PBS_BATCH_Shutdown: rc = decode_DIS_ShutDown(chan, request); break; case PBS_BATCH_SignalJob: rc = decode_DIS_SignalJob(chan, request); break; case PBS_BATCH_StatusJob: rc = decode_DIS_Status(chan, request); break; case PBS_BATCH_GpuCtrl: rc = decode_DIS_GpuCtrl(chan, request); break; #ifndef PBS_MOM case PBS_BATCH_LocateJob: rc = decode_DIS_JobId(chan, request->rq_ind.rq_locate); break; case PBS_BATCH_Manager: case PBS_BATCH_ReleaseJob: rc = decode_DIS_Manage(chan, request); break; case PBS_BATCH_MoveJob: case PBS_BATCH_OrderJob: rc = decode_DIS_MoveJob(chan, request); break; case PBS_BATCH_RunJob: case PBS_BATCH_AsyrunJob: case PBS_BATCH_StageIn: rc = decode_DIS_RunJob(chan, request); break; case PBS_BATCH_SelectJobs: case PBS_BATCH_SelStat: CLEAR_HEAD(request->rq_ind.rq_select); rc = decode_DIS_svrattrl(chan, &request->rq_ind.rq_select); break; case PBS_BATCH_StatusNode: case PBS_BATCH_StatusQue: case PBS_BATCH_StatusSvr: /* DIAGTODO: add PBS_BATCH_StatusDiag */ rc = decode_DIS_Status(chan, request); break; case PBS_BATCH_TrackJob: rc = decode_DIS_TrackJob(chan, request); break; case PBS_BATCH_Rescq: case PBS_BATCH_ReserveResc: case PBS_BATCH_ReleaseResc: rc = decode_DIS_Rescl(chan, request); break; case PBS_BATCH_RegistDep: rc = decode_DIS_Register(chan, request); break; case PBS_BATCH_AuthenUser: rc = decode_DIS_Authen(chan, request); break; case PBS_BATCH_AltAuthenUser: rc = decode_DIS_AltAuthen(chan, request); break; case PBS_BATCH_JobObit: rc = decode_DIS_JobObit(chan, request); break; #else /* PBS_MOM */ /* pbs_mom services */ case PBS_BATCH_DeleteReservation: /* NO-OP: this one is just a header and an extension string */ break; case PBS_BATCH_ReturnFiles: rc = decode_DIS_ReturnFiles(chan, request); break; case PBS_BATCH_CopyFiles: case PBS_BATCH_DelFiles: rc = decode_DIS_CopyFiles(chan, request); break; #endif /* PBS_MOM */ default: sprintf(log_buf, "%s: %d from %s", pbse_to_txt(PBSE_NOSUP), request->rq_type, request->rq_user); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, __func__, log_buf); rc = PBSE_UNKREQ; break; } /* END switch (request->rq_type) */ if (rc == DIS_SUCCESS) { /* Decode the Request Extension, if present */ rc = decode_DIS_ReqExtend(chan, request); if (rc != 0) { sprintf(log_buf, "req extension bad, dis error %d (%s), type=%s", rc, dis_emsg[rc], reqtype_to_txt(request->rq_type)); log_event(PBSEVENT_DEBUG,PBS_EVENTCLASS_REQUEST,"?",log_buf); rc = PBSE_DISPROTO; } } else if (rc != PBSE_UNKREQ) { sprintf(log_buf, "req body bad, dis error %d (%s), type=%s", rc, dis_emsg[rc], reqtype_to_txt(request->rq_type)); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, "?", log_buf); rc = PBSE_DISPROTO; } return(rc); } /* END dis_request_read() */