static krb5_error_code acl_renprinc(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, krb5_const_principal src, krb5_const_principal dest) { struct kadm5_auth_restrictions *rs; if (acl_check(data, ACL_DELETE, client, src, NULL) == 0 && acl_check(data, ACL_ADD, client, dest, &rs) == 0 && rs == NULL) return 0; return KRB5_PLUGIN_NO_HANDLE; }
static krb5_error_code acl_modpol(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, const char *policy, const struct _kadm5_policy_ent_t *ent, long mask) { return acl_check(data, ACL_MODIFY, client, NULL, NULL); }
static krb5_error_code acl_getpol(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, const char *policy, const char *client_policy) { return acl_check(data, ACL_INQUIRE, client, NULL, NULL); }
static krb5_error_code acl_setstr(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, krb5_const_principal target, const char *key, const char *value) { return acl_check(data, ACL_MODIFY, client, target, NULL); }
static krb5_error_code acl_modprinc(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, krb5_const_principal target, const struct _kadm5_principal_ent_t *ent, long mask, struct kadm5_auth_restrictions **rs_out) { return acl_check(data, ACL_MODIFY, client, target, rs_out); }
int main(int argc, char **argv) { struct rekey_session *sess; krb5_principal subject; struct ACL *acl; FILE *F; char *string_acl[3], **x; int rc, exact = 0; if (argc < 2) usage(); switch ((*++argv)[0]) { case 'b': if (argc < 3) usage(); exact = ((*argv)[1] == 'e'); sess = setup_session(); acl = acl_load_builtin(sess, "<builtin>", builtin_acl); break; case 'f': if (argc < 4) usage(); exact = ((*argv)[1] == 'e'); sess = setup_session(); acl = acl_load(sess, *++argv); break; case 's': if (argc < 4) usage(); exact = ((*argv)[1] == 'e'); sess = setup_session(); string_acl[0] = *++argv; if (**argv == '!') { string_acl[1] = "**@REKEY.EXAMPLE"; string_acl[2] = 0; } else { string_acl[1] = 0; } acl = acl_load_builtin(sess, "<string>", string_acl); break; case 'o': if (argc < 3) usage(); if (!(F = fopen(*++argv, "w"))) fatal("%s: %s\n", *argv, strerror(errno)); for (x = builtin_acl; *x; x++) fprintf(F, "%s\n", *x); fclose(F); exit(0); default: usage(); } if ((rc = krb5_parse_name(sess->kctx, *++argv, &subject))) fatal("%s: %s\n", *argv, krb5_get_err_text(sess->kctx, rc)); rc = acl_check(sess, acl, subject, exact); exit(rc ? 0 : 99); }
END_TEST START_TEST(test_two) { pbs_attribute attr; server_host = (char *)"bdaw.ac"; memset(&attr,0,sizeof(attr)); decode_arst(&attr,NULL,NULL,"[email protected],[email protected],[email protected]",0); fail_unless(acl_check(&attr,(char *)"*****@*****.**",ACL_User)==1); free_arst(&attr); memset(&attr,0,sizeof(attr)); decode_arst(&attr,NULL,NULL,"[email protected],[email protected],[email protected]",0); fail_unless(acl_check(&attr,(char *)"*****@*****.**",ACL_User)==0); free_arst(&attr); memset(&attr,0,sizeof(attr)); decode_arst(&attr,NULL,NULL,"braddaw.com,gmail.com,farmer.org,host[0-7]",0); fail_unless(acl_check(&attr,(char *)"host0",ACL_Host)==1); fail_unless(acl_check(&attr,(char *)"host8",ACL_Host)==0); free_arst(&attr); memset(&attr,0,sizeof(attr)); decode_arst(&attr,NULL,NULL,"braddaw.com,gmail.com,farmer.org,host*",0); fail_unless(acl_check(&attr,(char *)"host0",ACL_Host)==1); fail_unless(acl_check(&attr,(char *)"heist8",ACL_Host)==0); free_arst(&attr); }
static int rescan_client_acls(void) { struct worker_t *w = worker_threads; struct client_t *c; struct listen_t *l; int pe; hlog(LOG_DEBUG, "Scanning old clients against new ACLs and listeners"); while (w) { if ((pe = pthread_mutex_lock(&w->clients_mutex))) { hlog(LOG_ERR, "rescan_client_acls(worker %d): could not lock clients_mutex: %s", w->id, strerror(pe)); return -1; } for (c = w->clients; (c); c = c->next) { /* do not disconnect uplinks at this point */ if (!(c->flags & CLFLAGS_INPORT)) continue; l = find_listener_hash_id(c->listener_id); if (!l) { /* listener is not there any more */ hlog(LOG_INFO, "%s - Closing client on fd %d from %s (listener has been removed)", c->addr_loc, c->fd, c->addr_rem); shutdown(c->fd, SHUT_RDWR); continue; } /* is there an acl? */ if (!l->acl) continue; /* there is, check */ if (!acl_check(l->acl, (struct sockaddr *)&c->addr, sizeof(c->addr))) { hlog(LOG_INFO, "%s - Denying client on fd %d from %s (new ACL)", c->addr_loc, c->fd, c->addr_rem); shutdown(c->fd, SHUT_RDWR); continue; } } if ((pe = pthread_mutex_unlock(&w->clients_mutex))) { hlog(LOG_ERR, "rescan_client_acls(worker %d): could not unlock clients_mutex: %s", w->id, strerror(pe)); /* we'd going to deadlock here... */ exit(1); } w = w->next; } return 0; }
/* 23.4.28 */ int acl_valid(acl_t acl) { int result; result = acl_check(acl, NULL); if (result != 0) { if (result > 0) errno = EINVAL; return -1; } return 0; }
int authenticate_user(struct batch_request *preq, struct connection *pcred) { char uath[PBS_MAXUSER + PBS_MAXHOSTNAME + 1]; #if defined(PBS_SECURITY) && ((PBS_SECURITY == KAUTH ) || (PBS_SECURITY == KCRYPT ) ) strcpy(pcred->cn_username, preq->rq_user); strcpy(pcred->cn_hostname, preq->rq_host); #endif if (strncmp(preq->rq_user, pcred->cn_username, PBS_MAXUSER)) return (PBSE_BADCRED); if (strncasecmp(preq->rq_host, pcred->cn_hostname, PBS_MAXHOSTNAME)) return (PBSE_BADCRED); if (pcred->cn_timestamp) { if ((pcred->cn_timestamp - CREDENTIAL_TIME_DELTA > time_now) || (pcred->cn_timestamp + CREDENTIAL_LIFETIME < time_now)) return (PBSE_EXPIRED); } /* If Server's Acl_User enabled, check if user in list */ if (server.sv_attr[SRV_ATR_AclUserEnabled].at_val.at_long) { (void)strcpy(uath, preq->rq_user); (void)strcat(uath, "@"); (void)strcat(uath, preq->rq_host); if (acl_check(&server.sv_attr[SRV_ATR_AclUsers], uath, ACL_User) == 0) { /* not in list, next check if listed as a manager */ if ((svr_get_privilege(preq->rq_user, preq->rq_host) & (ATR_DFLAG_MGWR | ATR_DFLAG_OPWR)) == 0) return (PBSE_PERM); } } /* A site stub for additional checking */ return (site_allow_u(preq->rq_user, preq->rq_host)); }
int set_jobexid( job *pjob, /* I */ attribute *attrry, /* I */ char *EMsg) /* O (optional,minsize=1024) */ { int addflags = 0; attribute *pattr; char **pmem; struct group *gpent; char *puser = NULL; char *id = "set_jobexid"; char *at; char *usr_at_host = NULL; int len; struct passwd *pwent = NULL; char *pgrpn; char gname[PBS_MAXGRPN + 1]; #ifdef _CRAY struct udb *pudb; #endif char tmpLine[1024 + 1]; int CheckID; /* boolean */ if (EMsg != NULL) EMsg[0] = '\0'; /* use the passed User_List if set, may be a newly modified one */ /* if not set, fall back to the job's actual User_List, may be same */ if (server.sv_attr[(int)SRV_ATR_DisableServerIdCheck].at_val.at_long) CheckID = 0; else CheckID = 1; if (CheckID == 0) { /* NOTE: use owner, not userlist - should this be changed? */ /* Yes, changed 10/17/2007 */ if (pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str != NULL) { /* start of change to use userlist instead of owner 10/17/2007 */ if ((attrry + (int)JOB_ATR_userlst)->at_flags & ATR_VFLAG_SET) pattr = attrry + (int)JOB_ATR_userlst; else pattr = &pjob->ji_wattr[(int)JOB_ATR_userlst]; if (pjob->ji_wattr[JOB_ATR_proxy_user].at_flags & ATR_VFLAG_SET) { puser = pjob->ji_wattr[JOB_ATR_proxy_user].at_val.at_str; /* set the job's owner as the new user, appending @host if * the job's owner has that */ at = strchr(pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str,'@'); len = strlen(puser) + 1; if (at != NULL) { len += strlen(at); usr_at_host = (char *)malloc(len * sizeof(char)); snprintf(usr_at_host,len,"%s%s", puser, at); } else { usr_at_host = (char *)malloc(len * sizeof(char)); snprintf(usr_at_host,len,"%s", puser); } free(pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str); pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str = usr_at_host; } else if ((puser = geteusernam(pjob, pattr)) == NULL) { if (EMsg != NULL) snprintf(EMsg, 1024, "cannot locate user name in job"); return(PBSE_BADUSER); } sprintf(tmpLine, "%s", puser); /* end of change to use userlist instead of owner 10/17/2007 */ } else { strcpy(tmpLine, "???"); } } /* END if (CheckID == 0) */ else { int perm; if ((attrry + (int)JOB_ATR_userlst)->at_flags & ATR_VFLAG_SET) pattr = attrry + (int)JOB_ATR_userlst; else pattr = &pjob->ji_wattr[(int)JOB_ATR_userlst]; if ((puser = geteusernam(pjob, pattr)) == NULL) { if (EMsg != NULL) snprintf(EMsg, 1024, "cannot locate user name in job"); return(PBSE_BADUSER); } pwent = getpwnam_ext(puser); perm = svr_get_privilege(puser,get_variable(pjob,"PBS_O_HOST")); if (pwent == NULL) { snprintf(log_buffer,sizeof(log_buffer), "User %s does not exist in server password file\n", puser); log_err(errno, id, log_buffer); if (EMsg != NULL) snprintf(EMsg,1024,"%s",log_buffer); return(PBSE_BADUSER); } if ((pwent->pw_uid == 0) || (perm & ATR_DFLAG_MGWR)) { /* add check here for virtual user */ if (pjob->ji_wattr[JOB_ATR_proxy_user].at_flags & ATR_VFLAG_SET) { puser = pjob->ji_wattr[JOB_ATR_proxy_user].at_val.at_str; pwent = getpwnam_ext(puser); if (pwent == NULL) { snprintf(log_buffer,sizeof(log_buffer), "User %s does not exist in server password file\n", puser); log_err(errno, id, log_buffer); if (EMsg != NULL) snprintf(EMsg,1024,"%s",log_buffer); return(PBSE_BADUSER); } /* set the job's owner as the new user */ at = strchr(pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str,'@'); len = strlen(puser) + 1; if (at != NULL) { len += strlen(at); usr_at_host = (char *)malloc(len * sizeof(char)); snprintf(usr_at_host,len,"%s%s", puser, at); } else { usr_at_host = (char *)malloc(len * sizeof(char)); snprintf(usr_at_host,len,"%s", puser); } free(pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str); pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str = usr_at_host; } else if (server.sv_attr[(int)SRV_ATR_AclRoot].at_flags & ATR_VFLAG_SET) { if (acl_check( &server.sv_attr[(int)SRV_ATR_AclRoot], pjob->ji_wattr[(int)JOB_ATR_job_owner].at_val.at_str, ACL_User) == 0) { if (EMsg != NULL) snprintf(EMsg, 1024, "root user %s fails ACL check", puser); return(PBSE_BADUSER); /* root not allowed */ } } else if (pwent->pw_uid == 0) { if (EMsg != NULL) snprintf(EMsg, 1024, "root user %s not allowed", puser); return(PBSE_BADUSER); /* root not allowed */ } } /* END if (pwent->pw_uid == 0) */ else if (pjob->ji_wattr[JOB_ATR_proxy_user].at_flags & ATR_VFLAG_SET) { /* cannot submit a proxy job if not root or a manager */ if (EMsg != NULL) { snprintf(EMsg, 1024, "User '%s' is attempting to submit a proxy job for user '%s' but is not a manager", puser, pjob->ji_wattr[JOB_ATR_proxy_user].at_val.at_str); } snprintf(log_buffer, 1024, "User '%s' is attempting to submit a proxy job for user '%s' but is not a manager", puser, pjob->ji_wattr[JOB_ATR_proxy_user].at_val.at_str); log_err(PBSE_BADUSER, id, log_buffer); return(PBSE_BADUSER); } if (site_check_user_map(pjob, puser, EMsg) == -1) { return(PBSE_BADUSER); } strncpy(tmpLine, puser, sizeof(tmpLine)); } /* END else (CheckID == 0) */ pattr = attrry + (int)JOB_ATR_euser; job_attr_def[(int)JOB_ATR_euser].at_free(pattr); job_attr_def[(int)JOB_ATR_euser].at_decode(pattr, NULL, NULL, tmpLine); #ifdef _CRAY /* on cray check UDB (user data base) for permission to batch it */ if ((pwent != NULL) && (puser != NULL)) { pudb = getudbuid(pwent->pw_uid); endudb(); if (pudb == UDB_NULL) { if (EMsg != NULL) snprintf(EMsg, 1024, "user %s not located in user data base", puser); return(PBSE_BADUSER); } if (pudb->ue_permbits & (PERMBITS_NOBATCH | PERMBITS_RESTRICTED)) { return(PBSE_QACESS); } /* if account (qsub -A) not specified, set default from UDB */ pattr = attrry + (int)JOB_ATR_account; if ((pattr->at_flags & ATR_VFLAG_SET) == 0) { job_attr_def[(int)JOB_ATR_account].at_decode( pattr, NULL, NULL, (char *)acid2nam(pudb->ue_acids[0])); } } /* END if ((pwent != NULL) && (puser != NULL)) */ #endif /* _CRAY */ /* * now figure out the group name under which the job should execute * PBS requires that each group have an entry in the group file, * see the admin guide for the reason why... * * use the passed group_list if set, may be a newly modified one * if not set, fall back to the job's actual group_list, may be same */ if ((attrry + (int)JOB_ATR_grouplst)->at_flags & ATR_VFLAG_SET) pattr = attrry + (int)JOB_ATR_grouplst; else pattr = &pjob->ji_wattr[(int)JOB_ATR_grouplst]; /* extract user-specified egroup if it exists */ pgrpn = getegroup(pjob, pattr); if (pgrpn == NULL) { if ((pwent != NULL) || ((pwent = getpwnam_ext(puser)) != NULL)) { /* egroup not specified - use user login group */ gpent = getgrgid(pwent->pw_gid); if (gpent != NULL) { pgrpn = gpent->gr_name; /* use group name */ } else { sprintf(gname, "%ld", (long)pwent->pw_gid); pgrpn = gname; /* turn gid into string */ } } else if (CheckID == 0) { strcpy(gname, "???"); pgrpn = gname; } else { log_err(errno, id, "getpwnam failed"); if (EMsg != NULL) snprintf(EMsg, 1024, "user does not exist in server password file"); return(PBSE_BADUSER); } /* * setting the DEFAULT flag is a "kludgy" way to keep MOM from * having to do an unneeded look up of the group file. * We needed to have JOB_ATR_egroup set for the server but * MOM only wants it if it is not the login group, so there! */ addflags = ATR_VFLAG_DEFLT; } /* END if ((pgrpn = getegroup(pjob,pattr))) */ else if (CheckID == 0) { /* egroup specified - do not validate group within server */ /* NO-OP */ } else { /* user specified a group, group must exist and either */ /* must be user's primary group or the user must be in it */ gpent = getgrnam_ext(pgrpn); if (gpent == NULL) { if (CheckID == 0) { strcpy(gname, "???"); pgrpn = gname; } else if (EMsg != NULL) snprintf(EMsg, 1024, "cannot locate group %s in server group file", pgrpn); return(PBSE_BADGRP); /* no such group */ } if (gpent->gr_gid != pwent->pw_gid) { /* not primary group */ pmem = gpent->gr_mem; while (*pmem != NULL) { if (!strcmp(puser, *pmem)) break; ++pmem; } if (*pmem == NULL) { /* requested group not allowed */ snprintf(log_buffer,sizeof(log_buffer), "user %s is not a member of group %s in server password file", puser, pgrpn); log_err(-1,id,log_buffer); if (EMsg != NULL) snprintf(EMsg, 1024, "%s",log_buffer); return(PBSE_BADGRP); /* user not in group */ } } } /* END if ((pgrpn = getegroup(pjob,pattr))) */ /* set new group */ pattr = attrry + (int)JOB_ATR_egroup; job_attr_def[(int)JOB_ATR_egroup].at_free(pattr); job_attr_def[(int)JOB_ATR_egroup].at_decode(pattr, NULL, NULL, pgrpn); pattr->at_flags |= addflags; /* SUCCESS */ return(0); } /* END set_jobexid() */
static krb5_error_code acl_extract(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, krb5_const_principal target) { return acl_check(data, ACL_EXTRACT, client, target, NULL); }
static krb5_error_code acl_getstrs(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, krb5_const_principal target) { return acl_check(data, ACL_INQUIRE, client, target, NULL); }
void client_io(struct context *ctx, int cur) { /* We have incoming data. */ char *serial; int res; ssize_t buflen; sockaddr_union sa; socklen_t sinlen = (socklen_t) sizeof(sockaddr_union); char *avt; char buf[BUFSIZE_MAVIS]; av_ctx *avc; static struct query *q = NULL; if (!q) q = Xcalloc(1, sizeof(struct query)); Debug((DEBUG_PROC, "client_io\n")); /* Receive request from client */ buflen = recvfrom(cur, buf, sizeof(buf) - 1, 0, &sa.sa, &sinlen); if (buflen <= 0) return; buf[buflen] = 0; /* Decode data, if neccessary */ if (ctx->blowfish) blowfish_dec(ctx->blowfish, (a_char *) buf, buflen); /* Check client IP address */ res = acl_check(&sa); if (!res) { char ibuf[INET6_ADDRSTRLEN]; logmsg("Ignoring query from %s", su_ntop(&sa, ibuf, (socklen_t) sizeof(ibuf))); return; } counter_query++, counter_p_query++; avc = av_new(NULL, NULL); av_char_to_array(avc, buf, NULL); serial = av_get(avc, AV_A_SERIAL); if (!serial) { char ibuf[INET6_ADDRSTRLEN]; logmsg("query from %s lacks serial", su_ntop(&sa, ibuf, (socklen_t) sizeof(ibuf))); counter_err++, counter_p_err++; av_free(avc); return; } q->serial = serial; q->serial_crc = crc32_update(INITCRC32, (u_char *) serial, strlen(serial)); if (RB_search(deferred_by_serial, q)) { char ibuf[INET6_ADDRSTRLEN]; Debug((DEBUG_PROC, "Duplicate detected\n")); logmsg("Ignoring duplicate query from %s (backlog: %d)", su_ntop(&sa, ibuf, (socklen_t) sizeof(ibuf)), backlog); counter_retry++, counter_p_retry++; av_free(avc); return; } if (av_get(avc, AV_A_RESULT)) { char ibuf[INET6_ADDRSTRLEN]; Debug((DEBUG_PROC, "AV_A_RESULT already set. Spoofing?\n")); logmsg("Ignoring query with pre-set result code " "from %s (backlog: %d)", su_ntop(&sa, ibuf, (socklen_t) sizeof(ibuf)), backlog); counter_err++, counter_p_err++; av_free(avc); return; } avt = av_get(avc, AV_A_TYPE); if (!avt || !strncmp(avt, AV_V_TYPE_PRIVATE_PREFIX, AV_V_TYPE_PRIVATE_PREFIX_LEN)) { counter_err++, counter_p_err++; av_free(avc); return; } av_setcb(avc, (void *) mavis_io, (void *) q); switch (mavis_send(mcx, &avc)) { case MAVIS_DEFERRED: Debug((DEBUG_PROC, "mavis_send yields DEFERRED\n")); q->sa = sa; q->fd = cur; q->serial = Xstrdup(serial); RB_insert(deferred_by_serial, q); q = NULL; backlog++; if (backlog > backlog_max) backlog_max = backlog; if (backlog > backlog_max_p) backlog_max_p = backlog; setproctitle("%s: backlog: %d", common_data.progname, backlog); return; case MAVIS_TIMEOUT: counter_expired++, counter_p_expired++; break; case MAVIS_FINAL: if (!transmit_password) { av_unset(avc, AV_A_PASSWORD); av_unset(avc, AV_A_DBPASSWORD); } av_send(avc, cur, &sa, ctx->blowfish); counter_answered++, counter_p_answered++; } av_free(avc); }
int mime_acl_check(uschar *acl, FILE *f, struct mime_boundary_context *context, uschar **user_msgptr, uschar **log_msgptr) { int rc = OK; uschar * header = NULL; struct mime_boundary_context nested_context; /* reserve a line buffer to work in */ header = store_get(MIME_MAX_HEADER_SIZE+1); /* Not actually used at the moment, but will be vital to fixing * some RFC 2046 nonconformance later... */ nested_context.parent = context; /* loop through parts */ while(1) { /* reset all per-part mime variables */ mime_vars_reset(); /* If boundary is null, we assume that *f is positioned on the start of headers (for example, at the very beginning of a message. If a boundary is given, we must first advance to it to reach the start of the next header block. */ /* NOTE -- there's an error here -- RFC2046 specifically says to * check for outer boundaries. This code doesn't do that, and * I haven't fixed this. * * (I have moved partway towards adding support, however, by adding * a "parent" field to my new boundary-context structure.) */ if (context) for (;;) { if (!fgets(CS header, MIME_MAX_HEADER_SIZE, f)) { /* Hit EOF or read error. Ugh. */ DEBUG(D_acl) debug_printf("MIME: Hit EOF ...\n"); return rc; } /* boundary line must start with 2 dashes */ if ( Ustrncmp(header, "--", 2) == 0 && Ustrncmp(header+2, context->boundary, Ustrlen(context->boundary)) == 0 ) { /* found boundary */ if (Ustrncmp((header+2+Ustrlen(context->boundary)), "--", 2) == 0) { /* END boundary found */ DEBUG(D_acl) debug_printf("MIME: End boundary found %s\n", context->boundary); return rc; } DEBUG(D_acl) debug_printf("MIME: Next part with boundary %s\n", context->boundary); break; } } /* parse headers, set up expansion variables */ while (mime_get_header(f, header)) { struct mime_header * mh; /* look for interesting headers */ for (mh = mime_header_list; mh < mime_header_list + mime_header_list_size; mh++) if (strncmpic(mh->name, header, mh->namelen) == 0) { uschar * p = header + mh->namelen; uschar * q; /* grab the value (normalize to lower case) and copy to its corresponding expansion variable */ for (q = p; *q != ';' && *q; q++) ; *mh->value = string_copynlc(p, q-p); DEBUG(D_acl) debug_printf("MIME: found %s header, value is '%s'\n", mh->name, *mh->value); if (*(p = q)) p++; /* jump past the ; */ { uschar * mime_fname = NULL; uschar * mime_fname_rfc2231 = NULL; uschar * mime_filename_charset = NULL; BOOL decoding_failed = FALSE; /* grab all param=value tags on the remaining line, check if they are interesting */ while (*p) { mime_parameter * mp; DEBUG(D_acl) debug_printf("MIME: considering paramlist '%s'\n", p); if ( !mime_filename && strncmpic(CUS"content-disposition:", header, 20) == 0 && strncmpic(CUS"filename*", p, 9) == 0 ) { /* RFC 2231 filename */ uschar * q; /* find value of the filename */ p += 9; while(*p != '=' && *p) p++; if (*p) p++; /* p is filename or NUL */ q = mime_param_val(&p); /* p now trailing ; or NUL */ if (q && *q) { uschar * temp_string, * err_msg; int slen; /* build up an un-decoded filename over successive filename*= parameters (for use when 2047 decode fails) */ mime_fname_rfc2231 = string_sprintf("%#s%s", mime_fname_rfc2231, q); if (!decoding_failed) { int size; if (!mime_filename_charset) { uschar * s = q; /* look for a ' in the "filename" */ while(*s != '\'' && *s) s++; /* s is 1st ' or NUL */ if ((size = s-q) > 0) mime_filename_charset = string_copyn(q, size); if (*(p = s)) p++; while(*p == '\'') p++; /* p is after 2nd ' */ } else p = q; DEBUG(D_acl) debug_printf("MIME: charset %s fname '%s'\n", mime_filename_charset ? mime_filename_charset : US"<NULL>", p); temp_string = rfc2231_to_2047(p, mime_filename_charset, &slen); DEBUG(D_acl) debug_printf("MIME: 2047-name %s\n", temp_string); temp_string = rfc2047_decode(temp_string, FALSE, NULL, ' ', NULL, &err_msg); DEBUG(D_acl) debug_printf("MIME: plain-name %s\n", temp_string); size = Ustrlen(temp_string); if (size == slen) decoding_failed = TRUE; else /* build up a decoded filename over successive filename*= parameters */ mime_filename = mime_fname = mime_fname ? string_sprintf("%s%s", mime_fname, temp_string) : temp_string; } } } else /* look for interesting parameters */ for (mp = mime_parameter_list; mp < mime_parameter_list + nelem(mime_parameter_list); mp++ ) if (strncmpic(mp->name, p, mp->namelen) == 0) { uschar * q; uschar * dummy_errstr; /* grab the value and copy to its expansion variable */ p += mp->namelen; q = mime_param_val(&p); /* p now trailing ; or NUL */ *mp->value = q && *q ? rfc2047_decode(q, check_rfc2047_length, NULL, 32, NULL, &dummy_errstr) : NULL; DEBUG(D_acl) debug_printf( "MIME: found %s parameter in %s header, value '%s'\n", mp->name, mh->name, *mp->value); break; /* done matching param names */ } /* There is something, but not one of our interesting parameters. Advance past the next semicolon */ p = mime_next_semicolon(p); if (*p) p++; } /* param scan on line */ if (strncmpic(CUS"content-disposition:", header, 20) == 0) { if (decoding_failed) mime_filename = mime_fname_rfc2231; DEBUG(D_acl) debug_printf( "MIME: found %s parameter in %s header, value is '%s'\n", "filename", mh->name, mime_filename); } } } } /* set additional flag variables (easier access) */ if ( mime_content_type && Ustrncmp(mime_content_type,"multipart",9) == 0 ) mime_is_multipart = 1; /* Make a copy of the boundary pointer. Required since mime_boundary is global and can be overwritten further down in recursion */ nested_context.boundary = mime_boundary; /* raise global counter */ mime_part_count++; /* copy current file handle to global variable */ mime_stream = f; mime_current_boundary = context ? context->boundary : 0; /* Note the context */ mime_is_coverletter = !(context && context->context == MBC_ATTACHMENT); /* call ACL handling function */ rc = acl_check(ACL_WHERE_MIME, NULL, acl, user_msgptr, log_msgptr); mime_stream = NULL; mime_current_boundary = NULL; if (rc != OK) break; /* If we have a multipart entity and a boundary, go recursive */ if ( (mime_content_type != NULL) && (nested_context.boundary != NULL) && (Ustrncmp(mime_content_type,"multipart",9) == 0) ) { DEBUG(D_acl) debug_printf("MIME: Entering multipart recursion, boundary '%s'\n", nested_context.boundary); nested_context.context = context && context->context == MBC_ATTACHMENT ? MBC_ATTACHMENT : Ustrcmp(mime_content_type,"multipart/alternative") == 0 || Ustrcmp(mime_content_type,"multipart/related") == 0 ? MBC_COVERLETTER_ALL : MBC_COVERLETTER_ONESHOT; rc = mime_acl_check(acl, f, &nested_context, user_msgptr, log_msgptr); if (rc != OK) break; } else if ( (mime_content_type != NULL) && (Ustrncmp(mime_content_type,"message/rfc822",14) == 0) ) { const uschar *rfc822name = NULL; uschar filename[2048]; int file_nr = 0; int result = 0; /* must find first free sequential filename */ do { struct stat mystat; (void)string_format(filename, 2048, "%s/scan/%s/__rfc822_%05u", spool_directory, message_id, file_nr++); /* security break */ if (file_nr >= 128) goto NO_RFC822; result = stat(CS filename,&mystat); } while (result != -1); rfc822name = filename; /* decode RFC822 attachment */ mime_decoded_filename = NULL; mime_stream = f; mime_current_boundary = context ? context->boundary : NULL; mime_decode(&rfc822name); mime_stream = NULL; mime_current_boundary = NULL; if (!mime_decoded_filename) /* decoding failed */ { log_write(0, LOG_MAIN, "mime_regex acl condition warning - could not decode RFC822 MIME part to file."); rc = DEFER; goto out; } mime_decoded_filename = NULL; } NO_RFC822: /* If the boundary of this instance is NULL, we are finished here */ if (!context) break; if (context->context == MBC_COVERLETTER_ONESHOT) context->context = MBC_ATTACHMENT; } out: mime_vars_reset(); return rc; }
void process_request(int sfds) { int rc; struct batch_request *request; conn_t *conn; time_now = time(NULL); conn = get_conn(sfds); if (!conn) { log_event(PBSEVENT_SYSTEM, PBS_EVENTCLASS_REQUEST, LOG_ERR, "process_request", "did not find socket in connection table"); #ifdef WIN32 (void)closesocket(sfds); #else (void)close(sfds); #endif return; } if ((request = alloc_br(0)) == NULL) { log_event(PBSEVENT_SYSTEM, PBS_EVENTCLASS_REQUEST, LOG_ERR, "process_request", "Unable to allocate request structure"); close_conn(sfds); return; } request->rq_conn = sfds; /* * Read in the request and decode it to the internal request structure. */ if (get_connecthost(sfds, request->rq_host, PBS_MAXHOSTNAME)) { (void)sprintf(log_buffer, "%s: %lu", msg_reqbadhost, get_connectaddr(sfds)); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, LOG_DEBUG, "", log_buffer); req_reject(PBSE_BADHOST, 0, request); return; } #ifndef PBS_MOM if (conn->cn_active == FromClientDIS) { rc = dis_request_read(sfds, request); } else { log_event(PBSEVENT_SYSTEM, PBS_EVENTCLASS_REQUEST, LOG_ERR, "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) { /* End of file */ close_client(sfds); free_br(request); return; } else if ((rc == PBSE_SYSTEM) || (rc == PBSE_INTERNAL)) { /* read error, likely cannot send reply so just disconnect */ /* ??? not sure about this ??? */ close_client(sfds); free_br(request); return; } else if (rc > 0) { /* * request didn't decode, either garbage or unknown * request type, in ether case, return reject-reply */ req_reject(rc, 0, request); close_client(sfds); return; } #ifndef PBS_MOM /* If the request is coming on the socket we opened to the */ /* scheduler, change the "user" from "root" to "Scheduler" */ if (find_sched_from_sock(request->rq_conn) != NULL) { strncpy(request->rq_user, PBS_SCHED_DAEMON_NAME, PBS_MAXUSER); request->rq_user[PBS_MAXUSER] = '\0'; } #endif /* PBS_MOM */ (void)sprintf(log_buffer, msg_request, request->rq_type, request->rq_user, request->rq_host, sfds); log_event(PBSEVENT_DEBUG2, PBS_EVENTCLASS_REQUEST, LOG_DEBUG, "", log_buffer); /* is the request from a host acceptable to the server */ if (request->rq_type == PBS_BATCH_AuthExternal) { rc = authenticate_external(conn, request); if (rc == 0) reply_ack(request); else if (rc == -2) req_reject(PBSE_NOSUP, 0, request); else req_reject(PBSE_BADCRED, 0, request); return; } #ifndef PBS_MOM if (server.sv_attr[(int)SRV_ATR_acl_host_enable].at_val.at_long) { /* acl enabled, check it; always allow myself */ struct pbsnode *isanode = NULL; if ((server.sv_attr[SRV_ATR_acl_host_moms_enable].at_flags & ATR_VFLAG_SET) && (server.sv_attr[(int)SRV_ATR_acl_host_moms_enable].at_val.at_long == 1)) { isanode = find_nodebyaddr(get_connectaddr(sfds)); if ((isanode != NULL) && (isanode->nd_state & INUSE_DELETED)) isanode = NULL; } if (isanode == NULL) { if ((acl_check(&server.sv_attr[(int)SRV_ATR_acl_hosts], request->rq_host, ACL_Host) == 0) && (strcasecmp(server_host, request->rq_host) != 0)) { req_reject(PBSE_BADHOST, 0, request); close_client(sfds); return; } } } /* * determine source (user client or another server) of request. * set the permissions granted to the client */ if (conn->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 a 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 authorization. */ if (request->rq_type == PBS_BATCH_Connect) { req_connect(request); return; } if ((conn->cn_authen & PBS_NET_CONN_AUTHENTICATED) ==0) { rc = PBSE_BADCRED; } else { rc = authenticate_user(request, conn); } if (rc != 0) { req_reject(rc, 0, request); if (rc == PBSE_BADCRED) close_client(sfds); return; } request->rq_perm = svr_get_privilege(request->rq_user, request->rq_host); } /* if server shutting down, disallow new jobs and new running */ if (server.sv_attr[(int)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_UserCred: case PBS_BATCH_UserMigrate: 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); return; } } #else /* THIS CODE FOR MOM ONLY */ /* check connecting host against allowed list of ok clients */ if (!addrfind(conn->cn_addr)) { req_reject(PBSE_BADHOST, 0, request); close_client(sfds); return; } 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 /* * 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; }
static krb5_error_code acl_listpols(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client) { return acl_check(data, ACL_LIST, client, NULL, NULL); }
static krb5_error_code acl_chrand(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, krb5_const_principal target) { return acl_check(data, ACL_CHANGEPW, client, target, NULL); }
int svr_get_privilege(char *user, char *host) { int is_root = 0; int priv = (ATR_DFLAG_USRD | ATR_DFLAG_USWR); char uh[PBS_MAXUSER + PBS_MAXHOSTNAME + 2]; #ifdef WIN32 char server_host_netbios[MAX_COMPUTERNAME_LENGTH+1]; DWORD hsize = MAX_COMPUTERNAME_LENGTH; char current_domain[PBS_MAXHOSTNAME+1]; char server_host_domain[PBS_MAXHOSTNAME+1]; char user_s[PBS_MAXHOSTNAME+ UNLEN+2]; char *p = NULL; char *p0 = NULL; int ch = '\\'; #endif (void)strcpy(uh, user); (void)strcat(uh, "@"); (void)strcat(uh, host); #ifdef WIN32 /* Try to match requesting host against: */ /* localhost */ /* <server_host> */ /* <server_host_netbios_name> */ /* <server_host_netbios_name>.<windows_domain> */ if ( isAdminPrivilege(user) && \ ( (strcasecmp(host, server_host) == 0) || \ (strcasecmp(host, LOCALHOST_SHORTNAME) == 0) || \ (GetComputerName(server_host_netbios, &hsize) && \ (strcasecmp(host, server_host_netbios) == 0)) || \ (GetComputerDomainName(current_domain) && \ sprintf(server_host_domain, "%s.%s", server_host_netbios, current_domain) && \ (strcasecmp(host, server_host_domain) == 0)) ) ) { is_root = 1; } #else if (strcmp(user, PBS_DEFAULT_ADMIN) == 0) { char myhostname[PBS_MAXHOSTNAME+1]; /* First try without DNS lookup. */ if (strcasecmp(host, server_host) == 0) { is_root = 1; } else if (strcasecmp(host, LOCALHOST_SHORTNAME) == 0) { is_root = 1; } else if (strcasecmp(host, LOCALHOST_FULLNAME) == 0) { is_root = 1; } else { if (gethostname(myhostname, (sizeof(myhostname) - 1)) == -1) { myhostname[0] = '\0'; } if (strcasecmp(host, myhostname) == 0) { is_root = 1; } } if (is_root == 0) { /* Now try with DNS lookup. */ if (is_same_host(host, server_host)) { is_root = 1; } else if (is_same_host(host, myhostname)) { is_root = 1; } } } #endif /* WIN32 */ #ifdef PBS_ROOT_ALWAYS_ADMIN if (is_root) return (priv | ATR_DFLAG_MGRD | ATR_DFLAG_MGWR | ATR_DFLAG_OPRD | ATR_DFLAG_OPWR); #endif /* PBS_ROOT_ALWAYS_ADMIN */ if (!(server.sv_attr[(int)SRV_ATR_managers].at_flags & ATR_VFLAG_SET)) { if (is_root) priv |= (ATR_DFLAG_MGRD | ATR_DFLAG_MGWR); } else if (acl_check(&server.sv_attr[SRV_ATR_managers], uh, ACL_User)) priv |= (ATR_DFLAG_MGRD | ATR_DFLAG_MGWR); if (!(server.sv_attr[(int)SRV_ATR_operators].at_flags&ATR_VFLAG_SET)) { if (is_root) priv |= (ATR_DFLAG_OPRD | ATR_DFLAG_OPWR); } else if (acl_check(&server.sv_attr[SRV_ATR_operators], uh, ACL_User)) priv |= (ATR_DFLAG_OPRD | ATR_DFLAG_OPWR); return (priv); }
int svr_get_privilege( char *user, /* I */ char *host) /* I */ { int is_root = 0; int priv = (ATR_DFLAG_USRD | ATR_DFLAG_USWR); int num_host_chars; char uh[PBS_MAXUSER + PBS_MAXHOSTNAME + 2]; char host_no_port[PBS_MAXHOSTNAME+1]; char *colon_loc = NULL; char log_buf[LOCAL_LOG_BUF_SIZE]; char *other_host; int other_priv = 0; int my_err; pbs_net_t server_addr; pbs_net_t connect_addr; #ifndef __CYGWIN__ pbs_net_t local_server_addr; #endif if (!user) { sprintf(log_buf, "Invalid user: %s", "null"); log_record(PBSEVENT_SECURITY, PBS_EVENTCLASS_SERVER, __func__, log_buf); return(0); } /* user name cannot be longer than PBS_MAXUSER*/ if (strlen(user) > PBS_MAXUSER) { sprintf(log_buf, "Invalid user: %s", user); log_record(PBSEVENT_SECURITY, PBS_EVENTCLASS_SERVER, __func__, log_buf); return(0); } if (!host) return(0); colon_loc = strchr(host, ':'); /* if the request host has port information in it, we want to strip it out */ if (colon_loc == NULL) { /* no colon found */ num_host_chars = strlen(host); sprintf(host_no_port, "%s", host); } else { num_host_chars = colon_loc - host; /* actually remove the colon for host_no_port */ *colon_loc = '\0'; sprintf(host_no_port,"%s",host); *colon_loc = ':'; } /* num_host_chars cannot be more than PBS_MAXHOSTNAME */ if (num_host_chars > PBS_MAXHOSTNAME) { snprintf(log_buf, sizeof(log_buf), "Invalid host: %s", host); log_record(PBSEVENT_SECURITY, PBS_EVENTCLASS_SERVER, __func__, log_buf); return(0); } sprintf(uh, "%s@%s", user, host); server_addr = get_hostaddr(&my_err, server_host); connect_addr = get_hostaddr(&my_err, host_no_port); #ifdef __CYGWIN__ if ((IamAdminByName(user)) && (server_addr == connect_addr)) { return(priv | ATR_DFLAG_MGRD | ATR_DFLAG_MGWR | ATR_DFLAG_OPRD | ATR_DFLAG_OPWR); } #else /* __CYGWIN__ */ local_server_addr = get_hostaddr(&my_err, server_localhost); if ((strcmp(user, PBS_DEFAULT_ADMIN) == 0) && ((connect_addr == server_addr) || (connect_addr == local_server_addr))) { is_root = 1; #ifdef PBS_ROOT_ALWAYS_ADMIN if (is_root) { /* This statement allows us to compile with gcc-warnings */ /* if PBS_ROOT_ALWAYS_ADMIN is true is_root is assigned but never used */ ; } return(priv | ATR_DFLAG_MGRD | ATR_DFLAG_MGWR | ATR_DFLAG_OPRD | ATR_DFLAG_OPWR); #endif } #endif /* __CYGWIN__ */ pthread_mutex_lock(server.sv_attr_mutex); if (!(server.sv_attr[SRV_ATR_managers].at_flags & ATR_VFLAG_SET)) { #ifndef PBS_ROOT_ALWAYS_ADMIN if (is_root) priv |= (ATR_DFLAG_MGRD | ATR_DFLAG_MGWR); #endif } else if (acl_check(&server.sv_attr[SRV_ATR_managers], uh, ACL_User)) { priv |= (ATR_DFLAG_MGRD | ATR_DFLAG_MGWR); } if (!(server.sv_attr[SRV_ATR_operators].at_flags & ATR_VFLAG_SET)) { #ifndef PBS_ROOT_ALWAYS_ADMIN if (is_root) priv |= (ATR_DFLAG_OPRD | ATR_DFLAG_OPWR); #endif } else if (acl_check(&server.sv_attr[SRV_ATR_operators], uh, ACL_User)) { priv |= (ATR_DFLAG_OPRD | ATR_DFLAG_OPWR); } pthread_mutex_unlock(server.sv_attr_mutex); /* resolve using the other hostname (if available) and give the higher privilege */ other_host = get_cached_fullhostname(host, NULL); if ((other_host != NULL) && (strcmp(host, other_host))) other_priv = svr_get_privilege(user, other_host); if (other_priv > priv) priv = other_priv; return(priv); } /* END svr_get_privilege() */
/*===========================================================================* * main * *===========================================================================*/ int main(void) { message msg; int result, who_e, rcv_sts; int caller_slot; /* Initialize system so that all processes are runnable */ init_vm(); /* Register init callbacks. */ sef_setcb_init_restart(sef_cb_init_fail); sef_setcb_signal_handler(sef_cb_signal_handler); /* Let SEF perform startup. */ sef_startup(); SANITYCHECK(SCL_TOP); /* This is VM's main loop. */ while (TRUE) { int r, c; u32_t type, param; SANITYCHECK(SCL_TOP); if(missing_spares > 0) { alloc_cycle(); /* mem alloc code wants to be called */ } if ((r=sef_receive_status(ANY, &msg, &rcv_sts)) != OK) panic("sef_receive_status() error: %d", r); if (is_ipc_notify(rcv_sts)) { /* Unexpected notify(). */ printf("VM: ignoring notify() from %d\n", msg.m_source); continue; } who_e = msg.m_source; if(vm_isokendpt(who_e, &caller_slot) != OK) panic("invalid caller %d", who_e); type = param = msg.m_type; type &= 0x0000FFFF; param >>= 16; c = CALLNUMBER(type); result = ENOSYS; /* Out of range or restricted calls return this. */ if(msg.m_type == RS_INIT && msg.m_source == RS_PROC_NR) { result = do_rs_init(&msg); } else if (msg.m_type == VM_PAGEFAULT) { if (!IPC_STATUS_FLAGS_TEST(rcv_sts, IPC_FLG_MSG_FROM_KERNEL)) { printf("VM: process %d faked VM_PAGEFAULT " "message!\n", msg.m_source); } do_pagefaults(&msg); /* * do not reply to this call, the caller is unblocked by * a sys_vmctl() call in do_pagefaults if success. VM panics * otherwise */ continue; } else if(c < 0 || !vm_calls[c].vmc_func) { /* out of range or missing callnr */ } else { if (acl_check(&vmproc[caller_slot], c) != OK) { printf("VM: unauthorized %s by %d\n", vm_calls[c].vmc_name, who_e); } else { SANITYCHECK(SCL_FUNCTIONS); result = vm_calls[c].vmc_func(&msg); SANITYCHECK(SCL_FUNCTIONS); } } /* Send reply message, unless the return code is SUSPEND, * which is a pseudo-result suppressing the reply message. */ if(result != SUSPEND) { msg.m_type = result; if((r=send(who_e, &msg)) != OK) { printf("VM: couldn't send %d to %d (err %d)\n", msg.m_type, who_e, r); panic("send() error"); } } } return(OK); }
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() */
static krb5_error_code acl_delpol(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, const char *policy) { return acl_check(data, ACL_DELETE, client, NULL, NULL); }
static krb5_error_code acl_setkey(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, krb5_const_principal target) { return acl_check(data, ACL_SETKEY, client, target, NULL); }
int set_objexid(void *pobj, int objtype, attribute *attrry) { int addflags = 0; int isowner; attribute *pattr; char *puser; char *pgrpn; char *owner; int idx_ul, idx_gl; int idx_owner, idx_euser, idx_egroup; int idx_acct; int bad_euser, bad_egrp; attribute *objattrs; attribute_def *obj_attr_def; attribute *paclRoot; /*future: aclRoot resv != aclRoot job*/ #ifdef WIN32 char user_s[PBS_MAXHOSTNAME+ MAXNAMLEN+3]; char *p = NULL; char *p0 = NULL; int ch = '\\'; SID *sid; char *defgrp = NULL; #else char **pmem; struct group *gpent; struct passwd *pwent; char gname[PBS_MAXGRPN+1]; #endif /* determine index values and pointers based on object type */ if (objtype == JOB_OBJECT) { idx_ul = (int)JOB_ATR_userlst; idx_gl = (int)JOB_ATR_grouplst; idx_owner = (int)JOB_ATR_job_owner; idx_euser = (int)JOB_ATR_euser; idx_egroup = (int)JOB_ATR_egroup; idx_acct = (int)JOB_ATR_account; obj_attr_def = job_attr_def; objattrs = ((job *)pobj)->ji_wattr; owner = ((job *)pobj)->ji_wattr[idx_owner].at_val.at_str; paclRoot = &server.sv_attr[(int)SRV_ATR_AclRoot]; bad_euser = PBSE_BADUSER; bad_egrp = PBSE_BADGRP; } else { idx_ul = (int)RESV_ATR_userlst; idx_gl = (int)RESV_ATR_grouplst; idx_owner = (int)RESV_ATR_resv_owner; idx_euser = (int)RESV_ATR_euser; idx_egroup = (int)RESV_ATR_egroup; idx_acct = (int)RESV_ATR_account; obj_attr_def = resv_attr_def; objattrs = ((resc_resv *)pobj)->ri_wattr; owner = ((resc_resv *)pobj)->ri_wattr[idx_owner].at_val.at_str; paclRoot = &server.sv_attr[(int)SRV_ATR_AclRoot]; bad_euser = PBSE_R_UID; bad_egrp = PBSE_R_GID; } /* if passed in "User_List" attribute is set use it - this may * be a newly modified one. * if not set, fall back to the object's User_List, which may * actually be the same as what is passed into this function */ if ((attrry + idx_ul)->at_flags & ATR_VFLAG_SET) pattr = attrry + idx_ul; else pattr = &objattrs[idx_ul]; if ((puser = determine_euser(pobj, objtype, pattr, &isowner)) == NULL) return (bad_euser); #ifdef WIN32 if (isAdminPrivilege(puser)) { /* equivalent of root */ if ((paclRoot->at_flags & ATR_VFLAG_SET) == 0) return (bad_euser); /* root not allowed */ if (acl_check(paclRoot, owner, ACL_User) == 0) return (bad_euser); /* root not allowed */ } #else pwent = getpwnam(puser); if (pwent == NULL) { if (!server.sv_attr[(int)SRV_ATR_FlatUID].at_val.at_long) return (bad_euser); } else if (pwent->pw_uid == 0) { if ((paclRoot->at_flags & ATR_VFLAG_SET) == 0) return (bad_euser); /* root not allowed */ if (acl_check(paclRoot, owner, ACL_User) == 0) return (bad_euser); /* root not allowed */ } #endif if (!isowner || !server.sv_attr[(int)SRV_ATR_FlatUID].at_val.at_long) { #ifdef WIN32 if ( (server.sv_attr[SRV_ATR_ssignon_enable].at_flags & \ ATR_VFLAG_SET) && \ (server.sv_attr[SRV_ATR_ssignon_enable].at_val.at_long \ == 1) ) { /* read/cache user password */ cache_usertoken_and_homedir(puser, NULL, 0, user_read_password, (char *)puser, pbs_decrypt_pwd, 0); } else { /* read/cache job password */ cache_usertoken_and_homedir(puser, NULL, 0, read_cred, (job *)pobj, pbs_decrypt_pwd, 0); } #endif if (site_check_user_map(pobj, objtype, puser) == -1) return (bad_euser); } pattr = &objattrs[idx_euser]; obj_attr_def[idx_euser].at_free(pattr); obj_attr_def[idx_euser].at_decode(pattr, NULL, NULL, puser); #ifndef WIN32 if (pwent != NULL) { #endif /* if account (qsub -A) is not specified, set to empty string */ pattr = &objattrs[idx_acct]; if ((pattr->at_flags & ATR_VFLAG_SET) == 0) { (void)obj_attr_def[idx_acct].at_decode(pattr, NULL, NULL, "\0"); } /* * now figure out (for this host) the effective/execute "group name" * for the object. * PBS requires that each group have an entry in the group file, * see the admin guide for the reason why... * * use the passed group_list if set, may be a newly modified one. * if it isn't set, use the object's group_list, which may in fact * be same as what was passed */ if ((attrry + idx_gl)->at_flags & ATR_VFLAG_SET) pattr = attrry + idx_gl; else pattr = &objattrs[idx_gl]; if ((pgrpn = determine_egroup(pobj, objtype, pattr)) != NULL) { /* user specified a group, group must exists and either */ /* must be user's primary group or the user must be in it */ #ifdef WIN32 if ((sid=getgrpsid(pgrpn)) == NULL) return (bad_egrp); /* no such group */ (void)LocalFree(sid); #else gpent = getgrnam(pgrpn); if (gpent == NULL) { if (pwent != NULL) /* no such group is allowed */ return (bad_egrp); /* only when no user (flatuid)*/ } else if (gpent->gr_gid != pwent->pw_gid) { /* not primary */ pmem = gpent->gr_mem; while (*pmem) { if (!strcmp(puser, *pmem)) break; ++pmem; } if (*pmem == 0) return (bad_egrp); /* user not in group */ } #endif addflags = ATR_VFLAG_SET; } else { /* Use user login group */ #ifdef WIN32 if ((defgrp=getdefgrpname(puser)) == NULL) return (bad_egrp); /* set to a group that ALL users belong to as default */ pgrpn = defgrp; #else gpent = getgrgid(pwent->pw_gid); if (gpent != NULL) { pgrpn = gpent->gr_name; /* use group name */ } else { (void)sprintf(gname, "%d", pwent->pw_gid); pgrpn = gname; /* turn gid into string */ } #endif /* * setting the DEFAULT flag is a "kludy" way to keep MOM from * having to do an unneeded look up of the group file. * We needed to have JOB_ATR_egroup set for the server but * MOM only wants it if it is not the login group, so there! */ addflags = ATR_VFLAG_SET | ATR_VFLAG_DEFLT; } #ifndef WIN32 } else { /* * null password entry, * set group to "default" and set default for Mom to use login group */ pgrpn = "-default-"; addflags = ATR_VFLAG_SET | ATR_VFLAG_DEFLT; } #endif pattr = attrry + idx_egroup; obj_attr_def[idx_egroup].at_free(pattr); if (addflags != 0) { obj_attr_def[idx_egroup].at_decode(pattr, NULL, NULL, pgrpn); pattr->at_flags |= addflags; } #ifdef WIN32 if (defgrp) (void)free(defgrp); #endif return (0); }
static krb5_error_code acl_purgekeys(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, krb5_const_principal target) { return acl_check(data, ACL_MODIFY, client, target, NULL); }
static krb5_error_code acl_iprop(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client) { return acl_check(data, ACL_IPROP, client, NULL, NULL); }
static krb5_error_code acl_delprinc(krb5_context context, kadm5_auth_moddata data, krb5_const_principal client, krb5_const_principal target) { return acl_check(data, ACL_DELETE, client, target, NULL); }
int site_check_user_map( job *pjob, /* I */ char *luser, /* I */ char *EMsg) /* O (optional,minsize=1024) */ { char *orighost; char owner[PBS_MAXUSER + 1]; char *p1; char *p2; int rc; int ProxyAllowed = 0; int ProxyRequested = 0; int HostAllowed = 0; char *dptr; #ifdef MUNGE_AUTH char uh[PBS_MAXUSER + PBS_MAXHOSTNAME + 2]; #endif if (EMsg != NULL) EMsg[0] = '\0'; /* get just the owner name, without the "@host" */ p1 = pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str; p2 = owner; while ((*p1 != '@') && (*p1 != '\0')) *p2++ = *p1++; *p2 = '\0'; orighost = get_variable(pjob, pbs_o_host); if (orighost == NULL) { /* access denied */ log_event( PBSEVENT_JOB, PBS_EVENTCLASS_JOB, pjob->ji_qs.ji_jobid, msg_orighost); if (EMsg != NULL) strcpy(EMsg, "source host not specified"); return(-1); } if ((server.sv_attr[(int)SRV_ATR_AllowProxyUser].at_flags & ATR_VFLAG_SET) && \ (server.sv_attr[(int)SRV_ATR_AllowProxyUser].at_val.at_long == 1)) { ProxyAllowed = 1; } if (strcmp(owner, luser) != 0) { ProxyRequested = 1; } if (!strcmp(orighost, server_host) && !strcmp(owner, luser)) { /* submitting from server host, access allowed */ if ((ProxyRequested == 0) || (ProxyAllowed == 1)) { return(0); } /* host is fine, must validate proxy via ruserok() */ HostAllowed = 1; } /* make short host name */ if ((dptr = strchr(orighost, '.')) != NULL) { *dptr = '\0'; } if ((HostAllowed == 0) && (server.sv_attr[SRV_ATR_AllowNodeSubmit].at_flags & ATR_VFLAG_SET) && (server.sv_attr[SRV_ATR_AllowNodeSubmit].at_val.at_long == 1) && (find_nodebyname(orighost) != NULL)) { /* job submitted from compute host, access allowed */ if (dptr != NULL) *dptr = '.'; if ((ProxyRequested == 0) || (ProxyAllowed == 1)) { return(0); } /* host is fine, must validate proxy via ruserok() */ HostAllowed = 1; } if ((HostAllowed == 0) && (server.sv_attr[(int)SRV_ATR_SubmitHosts].at_flags & ATR_VFLAG_SET)) { struct array_strings *submithosts = NULL; char *testhost; int hostnum = 0; submithosts = server.sv_attr[(int)SRV_ATR_SubmitHosts].at_val.at_arst; for (hostnum = 0;hostnum < submithosts->as_usedptr;hostnum++) { testhost = submithosts->as_string[hostnum]; if (!strcasecmp(testhost, orighost)) { /* job submitted from host found in trusted submit host list, access allowed */ if (dptr != NULL) *dptr = '.'; if ((ProxyRequested == 0) || (ProxyAllowed == 1)) { return(0); } /* host is fine, must validate proxy via ruserok() */ HostAllowed = 1; break; } } /* END for (hostnum) */ } /* END if (SRV_ATR_SubmitHosts) */ if (dptr != NULL) *dptr = '.'; #ifdef MUNGE_AUTH sprintf(uh, "%s@%s", owner, orighost); rc = acl_check(&server.sv_attr[SRV_ATR_authusers], uh, ACL_User_Host); if(rc <= 0) { /* rc == 0 means we did not find a match. this is a failure */ if(EMsg != NULL) { snprintf(EMsg, 1024, "could not authorize user %s from %s", owner, orighost); } rc = -1; /* -1 is what set_jobexid is expecting for a failure*/ } else { /*SUCCESS*/ rc = 0; /* the call to ruserok below was in the code first. ruserok returns 0 on success but acl_check returns a positive value on success. We set rc to 0 to be consistent with the original ruserok functionality */ } #else rc = ruserok(orighost, 0, owner, luser); if (rc != 0 && EMsg != NULL) { /* Test rc so as to not fill this message in the case of success, since other * callers might not fill this message in the case of their errors and * very misleading error message will go into the logs. */ snprintf(EMsg, 1024, "ruserok failed validating %s/%s from %s", owner, luser, orighost); } #endif #ifdef sun /* broken Sun ruserok() sets process so it appears to be owned */ /* by the luser, change it back for cosmetic reasons */ setuid(0); #endif /* sun */ return(rc); } /* END site_check_user_map() */
int do_set( const char *path_p, const struct stat *st, const seq_t seq) { acl_t old_acl = NULL, old_default_acl = NULL; acl_t acl = NULL, default_acl = NULL; acl_t *xacl, *old_xacl; acl_entry_t ent; cmd_t cmd; int which_entry; int errors = 0, error; char *acl_text; int acl_modified = 0, default_acl_modified = 0; int acl_mask_provided = 0, default_acl_mask_provided = 0; /* Execute the commands in seq (read ACLs on demand) */ error = seq_get_cmd(seq, SEQ_FIRST_CMD, &cmd); if (error == 0) return 0; while (error == 1) { if (cmd->c_type == ACL_TYPE_ACCESS) { xacl = &acl; old_xacl = &old_acl; acl_modified = 1; if (cmd->c_tag == ACL_MASK) acl_mask_provided = 1; } else { xacl = &default_acl; old_xacl = &old_default_acl; default_acl_modified = 1; if (cmd->c_tag == ACL_MASK) default_acl_mask_provided = 1; } RETRIEVE_ACL(cmd->c_type); /* Check for `X', and replace with `x' as appropriate. */ if (cmd->c_perm & CMD_PERM_COND_EXECUTE) { cmd->c_perm &= ~CMD_PERM_COND_EXECUTE; if (S_ISDIR(st->st_mode) || has_execute_perms(*xacl)) cmd->c_perm |= CMD_PERM_EXECUTE; } switch(cmd->c_cmd) { case CMD_ENTRY_REPLACE: ent = find_entry(*xacl, cmd->c_tag, cmd->c_id); if (!ent) { if (acl_create_entry(xacl, &ent) != 0) goto fail; acl_set_tag_type(ent, cmd->c_tag); if (cmd->c_id != ACL_UNDEFINED_ID) acl_set_qualifier(ent, &cmd->c_id); } set_perm(ent, cmd->c_perm, ~cmd->c_perm); break; case CMD_ENTRY_ADD: ent = find_entry(*xacl, cmd->c_tag, cmd->c_id); if (ent) set_perm(ent, cmd->c_perm, 0); break; case CMD_ENTRY_SUBTRACT: ent = find_entry(*xacl, cmd->c_tag, cmd->c_id); if (ent) set_perm(ent, 0, cmd->c_perm); break; case CMD_REMOVE_ENTRY: ent = find_entry(*xacl, cmd->c_tag, cmd->c_id); if (ent) acl_delete_entry(*xacl, ent); else /* ignore */; break; case CMD_REMOVE_EXTENDED_ACL: remove_extended_entries(acl); break; case CMD_REMOVE_ACL: acl_free(*xacl); *xacl = acl_init(5); if (!*xacl) goto fail; break; default: errno = EINVAL; goto fail; } error = seq_get_cmd(seq, SEQ_NEXT_CMD, &cmd); } if (error < 0) goto fail; /* Try to fill in missing entries */ if (default_acl && acl_entries(default_acl) != 0) { xacl = &acl; old_xacl = &old_acl; if (!find_entry(default_acl, ACL_USER_OBJ, ACL_UNDEFINED_ID)) { if (!acl) RETRIEVE_ACL(ACL_TYPE_ACCESS); clone_entry(acl, ACL_USER_OBJ, &default_acl, ACL_USER_OBJ); } if (!find_entry(default_acl, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) { if (!acl) RETRIEVE_ACL(ACL_TYPE_ACCESS); clone_entry(acl, ACL_GROUP_OBJ, &default_acl, ACL_GROUP_OBJ); } if (!find_entry(default_acl, ACL_OTHER, ACL_UNDEFINED_ID)) { if (!acl) RETRIEVE_ACL(ACL_TYPE_ACCESS); clone_entry(acl, ACL_OTHER, &default_acl, ACL_OTHER); } } /* update mask entries and check if ACLs are valid */ if (acl && acl_modified) { if (acl_equiv_mode(acl, NULL) != 0) { if (!acl_mask_provided && !find_entry(acl, ACL_MASK, ACL_UNDEFINED_ID)) clone_entry(acl, ACL_GROUP_OBJ, &acl, ACL_MASK); if (opt_recalculate != -1 && (!acl_mask_provided || opt_recalculate == 1)) acl_calc_mask(&acl); } error = acl_check(acl, &which_entry); if (error < 0) goto fail; if (error > 0) { acl_text = acl_to_any_text(acl, NULL, ',', 0); fprintf(stderr, gettext("%s: %s: Malformed access ACL " "`%s': %s at entry %d\n"), progname, path_p, acl_text, acl_error(error), which_entry+1); acl_free(acl_text); errors++; goto cleanup; } } if (default_acl && acl_entries(default_acl) != 0 && default_acl_modified) { if (acl_equiv_mode(default_acl, NULL) != 0) { if (!default_acl_mask_provided && !find_entry(default_acl,ACL_MASK,ACL_UNDEFINED_ID)) clone_entry(default_acl, ACL_GROUP_OBJ, &default_acl, ACL_MASK); if (opt_recalculate != -1 && (!default_acl_mask_provided || opt_recalculate == 1)) acl_calc_mask(&default_acl); } error = acl_check(default_acl, &which_entry); if (error < 0) goto fail; if (error > 0) { acl_text = acl_to_any_text(default_acl, NULL, ',', 0); fprintf(stderr, gettext("%s: %s: Malformed default ACL " "`%s': %s at entry %d\n"), progname, path_p, acl_text, acl_error(error), which_entry+1); acl_free(acl_text); errors++; goto cleanup; } } /* Only directores can have default ACLs */ if (default_acl && !S_ISDIR(st->st_mode) && opt_recursive) { /* In recursive mode, ignore default ACLs for files */ acl_free(default_acl); default_acl = NULL; } /* check which ACLs have changed */ if (acl && old_acl && acl_cmp(old_acl, acl) == 0) { acl_free(acl); acl = NULL; } if ((default_acl && old_default_acl && acl_cmp(old_default_acl, default_acl) == 0)) { acl_free(default_acl); default_acl = NULL; } /* update the file system */ if (opt_test) { print_test(stdout, path_p, st, acl, default_acl); goto cleanup; } if (acl) { if (acl_set_file(path_p, ACL_TYPE_ACCESS, acl) != 0) { if (errno == ENOSYS || errno == ENOTSUP) { int saved_errno = errno; mode_t mode; if (acl_equiv_mode(acl, &mode) != 0) { errno = saved_errno; goto fail; } else if (chmod(path_p, mode) != 0) goto fail; } else goto fail; } } if (default_acl) { if (S_ISDIR(st->st_mode)) { if (acl_entries(default_acl) == 0) { if (acl_delete_def_file(path_p) != 0 && errno != ENOSYS && errno != ENOTSUP) goto fail; } else { if (acl_set_file(path_p, ACL_TYPE_DEFAULT, default_acl) != 0) goto fail; } } else { if (acl_entries(default_acl) != 0) { fprintf(stderr, gettext( "%s: %s: Only directories " "can have default ACLs\n"), progname, path_p); errors++; goto cleanup; } } } error = 0; cleanup: if (acl) acl_free(acl); if (old_acl) acl_free(old_acl); if (default_acl) acl_free(default_acl); if (old_default_acl) acl_free(old_default_acl); return errors; fail: fprintf(stderr, "%s: %s: %s\n", progname, path_p, strerror(errno)); errors++; goto cleanup; }