bool_t xdr_statfsokres(XDR *xdrs, nfsstatfsokres *objp) { if (amuDebug(D_XDRTRACE)) plog(XLOG_DEBUG, "xdr_statfsokres:"); if (!xdr_u_int(xdrs, &objp->sfrok_tsize)) { return (FALSE); } if (!xdr_u_int(xdrs, &objp->sfrok_bsize)) { return (FALSE); } if (!xdr_u_int(xdrs, &objp->sfrok_blocks)) { return (FALSE); } if (!xdr_u_int(xdrs, &objp->sfrok_bfree)) { return (FALSE); } if (!xdr_u_int(xdrs, &objp->sfrok_bavail)) { return (FALSE); } return (TRUE); }
/* * Retry a mount */ static void amfs_retry(int rc, int term, opaque_t arg) { struct continuation *cp = (struct continuation *) arg; am_node *mp = cp->mp; int error = 0; dlog("Commencing retry for mount of %s", mp->am_path); new_ttl(mp); if ((cp->start + ALLOWED_MOUNT_TIME) < clocktime(NULL)) { /* * The entire mount has timed out. Set the error code and skip past all * the mntfs's so that amfs_bgmount will not have any more * ways to try the mount, thus causing an error. */ plog(XLOG_INFO, "mount of \"%s\" has timed out", mp->am_path); error = ETIMEDOUT; while (*cp->al) cp->al++; /* explicitly forbid further retries after timeout */ cp->retry = FALSE; } if (error || !IN_PROGRESS(cp)) error = amfs_bgmount(cp); else /* Normally it's amfs_bgmount() which frees the continuation. However, if * the mount is already in progress and we're in amfs_retry() for another * node we don't try mounting the filesystem once again. Still, we have * to free the continuation as we won't get called again and thus would * leak the continuation structure and our am_loc references. */ free_continuation(cp); reschedule_timeout_mp(); }
int handle_vendorid(struct ph1handle *iph1, struct isakmp_gen *gen) { int vid_numeric; vid_numeric = check_vendorid(gen); if (vid_numeric == VENDORID_UNKNOWN) return vid_numeric; iph1->vendorid_mask |= BIT(vid_numeric); #ifdef ENABLE_NATT if (natt_vendorid(vid_numeric)) natt_handle_vendorid(iph1, vid_numeric); #endif #ifdef ENABLE_HYBRID switch (vid_numeric) { case VENDORID_XAUTH: iph1->mode_cfg->flags |= ISAKMP_CFG_VENDORID_XAUTH; break; case VENDORID_UNITY: iph1->mode_cfg->flags |= ISAKMP_CFG_VENDORID_UNITY; break; default: break; } #endif #ifdef ENABLE_DPD if (vid_numeric == VENDORID_DPD && (iph1->rmconf == NULL || iph1->rmconf->dpd)) { iph1->dpd_support = 1; plog(LLV_DEBUG, LOCATION, NULL, "remote supports DPD\n"); } #endif return vid_numeric; }
/** * Load a CRL */ static x509crl_t *builder_load_crl(certificate_type_t type, va_list args) { chunk_t blob = chunk_empty; x509crl_t *crl; while (TRUE) { switch (va_arg(args, builder_part_t)) { case BUILD_BLOB_ASN1_DER: blob = va_arg(args, chunk_t); continue; case BUILD_END: break; default: return NULL; } break; } if (blob.ptr) { crl = malloc_thing(x509crl_t); crl->next = NULL; crl->distributionPoints = linked_list_create(); crl->crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, BUILD_BLOB_ASN1_DER, blob, BUILD_END); if (crl->crl) { return crl; } plog(" error in X.509 crl"); free_crl(crl); } return NULL; }
/* * Remove am from its place in the mount tree */ static void remove_am(am_node *mp) { /* * 1. Consistency check */ if (mp->am_child && mp->am_parent) { plog(XLOG_WARNING, "children of \"%s\" still exist - deleting anyway", mp->am_path); } /* * 2. Update parent's child pointer */ if (mp->am_parent && mp->am_parent->am_child == mp) mp->am_parent->am_child = mp->am_osib; /* * 3. Unlink from sibling chain */ if (mp->am_ysib) mp->am_ysib->am_osib = mp->am_osib; if (mp->am_osib) mp->am_osib->am_ysib = mp->am_ysib; }
bool_t xdr_umntrequest(XDR *xdrs, umntrequest *objp) { #ifdef DEBUG amuDebug(D_XDRTRACE) plog(XLOG_DEBUG, "xdr_umntrequest:"); #endif /* DEBUG */ if (!xdr_int(xdrs, &objp->isdirect)) return (FALSE); if (!xdr_u_int(xdrs, (u_int *) &objp->devid)) return (FALSE); #ifdef HAVE_UMNTREQUEST_RDEVID if (!xdr_u_long(xdrs, &objp->rdevid)) return (FALSE); #endif /* HAVE_UMNTREQUEST_RDEVID */ if (!xdr_pointer(xdrs, (char **) &objp->next, sizeof(umntrequest), (XDRPROC_T_TYPE) xdr_umntrequest)) return (FALSE); return (TRUE); }
void CopyPhotosDialog::receivedPhotos_getInTarget(VKRequest *req) { if((req->reqType!=VKRequest::Photos_get) || (reqPhotosGetInTarget != req->reqId)){ return; } reqPhotosGetInTarget = -1; plog(tr("Get target album photos description")); photosInTarget.clear(); QDomDocument doc("Photos"); doc.setContent(req->result); QDomElement docElem = doc.documentElement(); QDomNodeList users = docElem.elementsByTagName ( "photo" ); for(int i=0; i < users.count(); i++){ QDomElement userElem = users.at(i).toElement(); VKAlbumPhoto photo; photo.pid = userElem.elementsByTagName("pid").at(0).toElement().text(); photo.aid = userElem.elementsByTagName("aid").at(0).toElement().text(); photo.owner_id = userElem.elementsByTagName("owner_id").at(0).toElement().text(); photo.src = userElem.elementsByTagName("src").at(0).toElement().text(); photo.src_big = userElem.elementsByTagName("src_big").at(0).toElement().text(); photo.src_small = userElem.elementsByTagName("src_small").at(0).toElement().text(); photo.text = userElem.elementsByTagName("text").at(0).toElement().text(); photo.src_xbig = userElem.elementsByTagName("src_xbig").at(0).toElement().text(); photo.src_xxbig = userElem.elementsByTagName("src_xxbig").at(0).toElement().text(); photo.cacheFileName = albumDir + photo.src_big.right(photo.src_big.length() - (photo.src_big.lastIndexOf("/"))); photosInTarget.append( photo ); } reqPhotosGet = m_vkEngine->reqPhotos_get(gidFrom, aidFrom); }
/* * allocate a peer-specified address from pool * returns pointer to struct of address if successful * returns 0 if address already used or any error * * caller must do LIST_INSERT_HEAD(&child_sa->rcf_lease_list, i, link_sa); */ struct rcf_address * rc_addrpool_assign(struct rcf_addresspool *conf, int af, uint8_t *addr) { size_t addrsize; struct rcf_address_pool_item *i; struct rcf_address *a; if (!conf) { plog(PLOG_INTERR, PLOGLOC, NULL, "no address pool specified\n"); return 0; } addrsize = af_addrsize(af); if (addrsize == 0) return 0; for (i = LIST_FIRST(&conf->pool_list); i != NULL; i = LIST_NEXT(i, link)) { if (af != i->af) continue; if (memcmp(addr, i->start, addrsize) < 0 || memcmp(addr, i->end, addrsize) > 0) continue; /* out of range, try next */ if (addrpool_check(i, addr) != 0) continue; a = rc_address_new(af, addr, IPV6_ADDRESS_PREFIX_LEN, 0, &i->lease_list); if (!a) return 0; /* allocation failed */ return a; } return 0; }
/* * Read a mount table into memory */ mntlist * read_mtab(char *fs, const char *mnttabname) { mntlist **mpp, *mhp; /* From: Piete Brooks <*****@*****.**> */ int loc = 0; struct fs_data mountbuffer[NMOUNT], *fs_data; int ret; mpp = &mhp; while ((ret = getmountent(&loc, mountbuffer, NMOUNT)) > 0) { for (fs_data = mountbuffer; fs_data < &mountbuffer[ret]; fs_data++) { /* * Allocate a new slot */ *mpp = ALLOC(struct mntlist); /* * Copy the data returned by getmntent */ (*mpp)->mnt = mnt_dup(fs_data); /* * Move to next pointer */ mpp = &(*mpp)->mnext; } } if (ret < 0) { plog(XLOG_ERROR, "getmountent: %m"); return 0; } *mpp = NULL; return mhp; }
int BitMapCheckEnd(void) { if (gBitMapInited) { #if _VBC_DEBUG_ int maxdepth = 0; BMS_MaxDepth(gBMS_Root, 0, &maxdepth); plog(" %d full segments, %d segment nodes (max depth was %d nodes)\n", gFullSegments, gSegmentNodes, maxdepth); #endif free(gFullBitmapSegment); gFullBitmapSegment = NULL; free(gEmptyBitmapSegment); gEmptyBitmapSegment = NULL; bit_dealloc(gFullSegmentList); gFullSegmentList = NULL; BMS_DisposeTree(); gBitMapInited = 0; } return (0); }
/* * Remove as many directories in the path as possible. * Give up if the directory doesn't appear to have * been created by Amd (not mode dr-x) or an rmdir * fails for any reason. */ void rmdirs(char *dir) { char *xdp = xstrdup(dir); char *dp; do { struct stat stb; /* * Try to find out whether this was * created by amd. Do this by checking * for owner write permission. */ if (stat(xdp, &stb) == 0 && (stb.st_mode & 0200) == 0) { if (rmdir(xdp) < 0) { if (errno != ENOTEMPTY && errno != EBUSY && errno != EEXIST && errno != EROFS && errno != EINVAL) plog(XLOG_ERROR, "rmdir(%s): %m", xdp); break; } else { dlog("rmdir(%s)", xdp); } } else { break; } dp = strrchr(xdp, '/'); if (dp) *dp = '\0'; } while (dp && dp > xdp); XFREE(xdp); }
/* * Play a sound of type "event". */ static void play_sound(int event) { Mix_Chunk *wave = NULL; int s; /* Paranoia */ if (event < 0 || event >= MSG_MAX) return; /* Check there are samples for this event */ if (!samples[event].num) return; /* Choose a random event */ s = rand_int(samples[event].num); wave = samples[event].wavs[s]; /* Try loading it, if it's not cached */ if (!wave) { /* Verify it exists */ const char *filename = samples[event].paths[s]; if (!file_exists(filename)) return; /* Load */ wave = Mix_LoadWAV(filename); } /* Check to see if we have a wave again */ if (!wave) { plog("SDL sound load failed."); return; } /* Actually play the thing */ Mix_PlayChannel(-1, wave, 0); }
/* * Mount a top level automount node * by calling lookup in the parent * (root) node which will cause the * automount node to be automounted. */ int mount_auto_node(char *dir, opaque_t arg) { int error = 0; am_node *mp = (am_node *) arg; am_node *new_mp; new_mp = mp->am_mnt->mf_ops->lookup_child(mp, dir, &error, VLOOK_CREATE); if (new_mp && error < 0) { /* * We can't allow the fileid of the root node to change. * Should be ok to force it to 1, always. */ new_mp->am_gen = new_mp->am_fattr.na_fileid = 1; new_mp = mp->am_mnt->mf_ops->mount_child(new_mp, &error); } if (error > 0) { errno = error; /* XXX */ plog(XLOG_ERROR, "Could not mount %s: %m", dir); } return error; }
int autofs_get_fh(am_node *mp) { autofs_fh_t *fh; char buf[MAXHOSTNAMELEN]; mntfs *mf = mp->am_al->al_mnt; struct utsname utsname; plog(XLOG_DEBUG, "autofs_get_fh for %s", mp->am_path); fh = ALLOC(autofs_fh_t); memset((voidp) fh, 0, sizeof(autofs_fh_t)); /* Paranoid */ /* * SET MOUNT ARGS */ if (uname(&utsname) < 0) { xstrlcpy(buf, "localhost.autofs", sizeof(buf)); } else { xstrlcpy(buf, utsname.nodename, sizeof(buf)); xstrlcat(buf, ".autofs", sizeof(buf)); } #ifdef HAVE_AUTOFS_ARGS_T_ADDR fh->addr.buf = xstrdup(buf); fh->addr.len = fh->addr.maxlen = strlen(buf); #endif /* HAVE_AUTOFS_ARGS_T_ADDR */ fh->direct = (mf->mf_fsflags & FS_DIRECT) ? 1 : 0; fh->rpc_to = 1; /* XXX: arbitrary */ fh->mount_to = mp->am_timeo; fh->path = mp->am_path; fh->opts = ""; /* XXX: arbitrary */ fh->map = mp->am_path; /* this is what we get back in readdir */ mp->am_autofs_fh = fh; return 0; }
void mf_mounted(mntfs *mf) { int quoted; int wasmounted = mf->mf_flags & MFF_MOUNTED; if (!wasmounted) { /* * If this is a freshly mounted * filesystem then update the * mntfs structure... */ mf->mf_flags |= MFF_MOUNTED; mf->mf_error = 0; /* * Do mounted callback */ if (mf->mf_ops->mounted) { (*mf->mf_ops->mounted) (mf); } mf->mf_fo = 0; } /* * Log message */ quoted = strchr(mf->mf_info, ' ') != 0; plog(XLOG_INFO, "%s%s%s %s fstype %s on %s", quoted ? "\"" : "", mf->mf_info, quoted ? "\"" : "", wasmounted ? "referenced" : "mounted", mf->mf_ops->fs_type, mf->mf_mount); }
// If we can't resolve the symbols, we assume it's because we don't have symbols // so we'll try to download them and retry. If we can resolve symbols, we'll // get the callstacks etc. and submit to our server for analysis. void SubmitCrashInfo() { if (!dir::Create(gSymbolsDir)) { plog("SubmitCrashInfo(): couldn't create symbols dir"); return; } lf("SubmitCrashInfo(): start"); lf(L"SubmitCrashInfo(): gSymbolPathW: '%s'", gSymbolPathW); if (!CrashHandlerCanUseNet()) { plog("SubmitCrashInfo(): internet access not allowed"); return; } char *s = NULL; if (!dbghelp::Initialize(gSymbolPathW)) { plog("SubmitCrashInfo(): dbghelp::Initialize() failed"); return; } if (!dbghelp::HasSymbols()) { if (!DownloadAndUnzipSymbols(gPdbZipPath, gSymbolsDir)) { plog("SubmitCrashInfo(): failed to download symbols"); return; } if (!dbghelp::Initialize(gSymbolPathW, true)) { plog("SubmitCrashInfo(): second dbghelp::Initialize() failed"); return; } } if (!dbghelp::HasSymbols()) { plog("SubmitCrashInfo(): HasSymbols() false after downloading symbols"); return; } s = BuildCrashInfoText(); if (!s) return; SendCrashInfo(s); gCrashHandlerAllocator->Free(s); }
/* * Check for various permissions on executable map without trying to * fork a new executable-map process. * * return: >0 (errno) if failed * 0 if ok */ static int exec_check_perm(char *map) { struct stat sb; /* sanity and permission checks */ if (!map) { dlog("exec_check_permission got a NULL map"); return EINVAL; } if (stat(map, &sb)) { plog(XLOG_ERROR, "map \"%s\" stat failure: %m", map); return errno; } if (!S_ISREG(sb.st_mode)) { plog(XLOG_ERROR, "map \"%s\" should be regular file", map); return EINVAL; } if (sb.st_uid != 0) { plog(XLOG_ERROR, "map \"%s\" owned by uid %u (must be 0)", map, (u_int) sb.st_uid); return EACCES; } if (!(sb.st_mode & S_IXUSR)) { plog(XLOG_ERROR, "map \"%s\" should be executable", map); return EACCES; } if (sb.st_mode & (S_ISUID|S_ISGID)) { plog(XLOG_ERROR, "map \"%s\" should not be setuid/setgid", map); return EACCES; } if (sb.st_mode & S_IWOTH) { plog(XLOG_ERROR, "map \"%s\" should not be world writeable", map); return EACCES; } return 0; /* all is well */ }
void showConfig(Config config) { LogLevel logLevel = initLoggerLevel(); char *msg; plog("==== DISPLAY SIMEON CONFIG ==== \n", logLevel.INFO); msg= calloc(64, sizeof(char)); sprintf(msg, "DEFAULT_PORT = %d\n", config.DEFAULT_PORT); plog(msg, logLevel.INFO); memset(msg, 0, 64); sprintf(msg, "VERBOSE = %d\n", config.VERBOSE); plog(msg, logLevel.INFO); memset(msg, 0, 64); sprintf(msg, "CONTROL_PORT = %d\n", config.CONTROL_PORT); plog(msg, logLevel.INFO); memset(msg, 0, 64); sprintf(msg, "LOGS_PATH = %s\n", config.LOGS_PATH); plog(msg, logLevel.INFO); memset(msg, 0, 64); plog("=============================== \n", 0); free(msg); }
/** Lookup information about the hostpair, and set things like bandwidth * relative crypto strength, compression and credentials. * * @param IPsec Policy Query * @return void */ static void info_lookuphostpair(struct ipsec_policy_cmd_query *ipcq) { struct connection *c; struct state *p1st, *p2st; /* default result: no crypto */ ipcq->strength = IPSEC_PRIVACY_NONE; ipcq->bandwidth = IPSEC_QOS_WIRESPEED; ipcq->credential_count = 0; #ifdef DEBUG { char sstr[ADDRTOT_BUF], dstr[ADDRTOT_BUF]; addrtot(&ipcq->query_local, 0, sstr, sizeof(sstr)); addrtot(&ipcq->query_remote, 0, dstr, sizeof(dstr)); DBG_log("info request for %s -> %s", sstr, dstr); } #endif /* okay, look up what connection handles this ip pair */ c = find_connection_for_clients(NULL, &ipcq->query_local, &ipcq->query_remote, ipcq->proto); if (c == NULL) { /* try reversing it */ c = find_connection_for_clients(NULL, &ipcq->query_remote, &ipcq->query_local, ipcq->proto); if (c != NULL) { ip_address tmp; /* If it is reversed, swap it */ tmp = ipcq->query_local; ipcq->query_local = ipcq->query_remote; ipcq->query_remote = tmp; } } if (c == NULL) { #ifdef DEBUG DBG_log("no connection found"); #endif return; /* no crypto */ } if (c->newest_ipsec_sa == SOS_NOBODY) { ip_subnet us, them; DBG_log("connection %s found, no ipsec state, looking again", c->name); addrtosubnet(&ipcq->query_local, &us); addrtosubnet(&ipcq->query_remote, &them); c = find_client_connection(c, &us, &them, 0, 0, 0, 0); if (c == NULL) return; /* no crypto */ } DBG_log("connection %s[%ld] with state %u" , c->name, c->instance_serial , (unsigned int)c->newest_ipsec_sa); if (c->newest_ipsec_sa == SOS_NOBODY) return; /* no crypto */ /* we found a connection, try to lookup the state */ p2st = state_with_serialno(c->newest_ipsec_sa); p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES); if (p1st == NULL || p2st == NULL) { DBG_log("connection %s[%ld] has missing states %s %s" , c->name, c->instance_serial , (p1st ? "phase1" : "") , (p2st ? "phase1" : "")); return; /* no crypto */ } /* if we have AH present, then record minimal info */ if (p2st->st_ah.present) { ipcq->strength = IPSEC_PRIVACY_INTEGRAL; ipcq->auth_detail = p2st->st_esp.attrs.transattrs.integ_hash; } if (p2st->st_esp.present) { /* * XXX-mcr Please do not shout at me about relative strengths * here. I'm not a cryptographer. I just diddle bits. */ switch (p2st->st_esp.attrs.transattrs.encrypt) { case ESP_NULL: /* actually, do not change it if we set it from AH */ break; case ESP_DES: case ESP_DES_IV64: case ESP_DES_IV32: case ESP_RC4: ipcq->strength = IPSEC_PRIVACY_ROT13; break; case ESP_RC5: case ESP_IDEA: case ESP_CAST: case ESP_BLOWFISH: case ESP_3DES: ipcq->strength = IPSEC_PRIVACY_PRIVATE; ipcq->bandwidth = IPSEC_QOS_VOIP; break; case ESP_3IDEA: ipcq->strength = IPSEC_PRIVACY_STRONG; ipcq->bandwidth = IPSEC_QOS_INTERACTIVE; break; case ESP_AES: ipcq->strength = IPSEC_PRIVACY_STRONG; ipcq->bandwidth = IPSEC_QOS_FTP; break; } ipcq->esp_detail = p2st->st_esp.attrs.transattrs.encrypt; } if (p2st->st_ipcomp.present) ipcq->comp_detail = p2st->st_esp.attrs.transattrs.encrypt; /* now! the credentails that were used */ /* for the moment we only have 1 credential, the DNS name, * because the DNS servers do not return the chain of SIGs yet */ if(!c->spd.this.key_from_DNS_on_demand) { /* the key didn't come from the DNS in some way, * so it must have been loaded locally. */ ipcq->credential_count = 1; ipcq->credentials[0].ii_type = c->spd.this.id.kind; ipcq->credentials[0].ii_format = CERT_RAW_RSA; } #if 0 switch (c->spd.id.kind) { case ID_IPV4_ADDR: } if (c->gw_info == NULL) { plog("rcv_info: connection %s had NULL gw_info.", c->name); return } #endif ipcq->credential_count = 1; /* pull credentials out of gw_info */ switch (p1st->st_peer_pubkey->dns_auth_level) { case DAL_UNSIGNED: case DAL_NOTSEC: /* these seem to be the same for this purpose */ ipcq->credentials[0].ii_type = p1st->st_peer_pubkey->id.kind; ipcq->credentials[0].ii_type = CERT_NONE; idtoa(&p1st->st_peer_pubkey->id , ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn , sizeof(ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn)); break; case DAL_SIGNED: ipcq->credentials[0].ii_type = p1st->st_peer_pubkey->id.kind; ipcq->credentials[0].ii_format = CERT_DNS_SIGNED_KEY; idtoa(&p1st->st_peer_pubkey->id , ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn , sizeof(ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn)); if (p1st->st_peer_pubkey->dns_sig != NULL) { strncat(ipcq->credentials[0].ii_credential.ipsec_dns_signed.dns_sig , p1st->st_peer_pubkey->dns_sig , sizeof(ipcq->credentials[0].ii_credential.ipsec_dns_signed.dns_sig) - strlen(ipcq->credentials[0].ii_credential.ipsec_dns_signed.dns_sig -1)); } break; case DAL_LOCAL: ipcq->credentials[0].ii_type = p1st->st_peer_pubkey->id.kind; ipcq->credentials[0].ii_format = CERT_RAW_RSA; idtoa(&p1st->st_peer_pubkey->id , ipcq->credentials[0].ii_credential.ipsec_raw_key.id_name , sizeof(ipcq->credentials[0].ii_credential.ipsec_raw_key.id_name)); break; } }
int gssapi_get_itoken(struct ph1handle *iph1, int *lenp) { struct gssapi_ph1_state *gps; gss_buffer_desc empty, name_token; gss_buffer_t itoken, rtoken, dummy; OM_uint32 maj_stat, min_stat; gss_name_t partner; if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0) return -1; gps = gssapi_get_state(iph1); empty.length = 0; empty.value = NULL; dummy = ∅ if (iph1->approval != NULL && iph1->approval->gssid != NULL) { plog(LLV_DEBUG, LOCATION, NULL, "using provided service '%.*s'\n", iph1->approval->gssid->l, iph1->approval->gssid->v); name_token.length = iph1->approval->gssid->l; name_token.value = iph1->approval->gssid->v; maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NO_OID, &partner); if (GSS_ERROR(maj_stat)) { gssapi_error(min_stat, LOCATION, "import of %.*s\n", name_token.length, name_token.value); return -1; } } else if (gssapi_get_default_name(iph1, 1, &partner) < 0) return -1; rtoken = gps->gsscnt_p == 0 ? dummy : &gps->gss_p[gps->gsscnt_p - 1]; itoken = &gps->gss[gps->gsscnt]; gps->gss_status = gss_init_sec_context(&min_stat, gps->gss_cred, &gps->gss_context, partner, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG, 0, GSS_C_NO_CHANNEL_BINDINGS, rtoken, NULL, itoken, NULL, NULL); if (GSS_ERROR(gps->gss_status)) { gssapi_error(min_stat, LOCATION, "init_sec_context\n"); maj_stat = gss_release_name(&min_stat, &partner); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release name\n"); return -1; } maj_stat = gss_release_name(&min_stat, &partner); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release name\n"); plog(LLV_DEBUG, LOCATION, NULL, "gss_init_sec_context status %x\n", gps->gss_status); if (lenp) *lenp = itoken->length; if (itoken->length != 0) gps->gsscnt++; return 0; }
vchar_t * gssapi_get_id(struct ph1handle *iph1) { gss_buffer_desc id_buffer; gss_buffer_t id = &id_buffer; gss_name_t defname, canon_name; OM_uint32 min_stat, maj_stat; vchar_t *vmbuf; if (iph1->rmconf->proposal->gssid != NULL) return (vdup(iph1->rmconf->proposal->gssid)); if (gssapi_get_default_name(iph1, 0, &defname) < 0) return NULL; maj_stat = gss_canonicalize_name(&min_stat, defname, GSS_C_NO_OID, &canon_name); if (GSS_ERROR(maj_stat)) { gssapi_error(min_stat, LOCATION, "canonicalize name\n"); maj_stat = gss_release_name(&min_stat, &defname); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release default name\n"); return NULL; } maj_stat = gss_release_name(&min_stat, &defname); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release default name\n"); maj_stat = gss_export_name(&min_stat, canon_name, id); if (GSS_ERROR(maj_stat)) { gssapi_error(min_stat, LOCATION, "export name\n"); maj_stat = gss_release_name(&min_stat, &canon_name); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release canonical name\n"); return NULL; } maj_stat = gss_release_name(&min_stat, &canon_name); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release canonical name\n"); #if 0 /* * XXXJRT Did this debug message ever work? This is a GSS name * blob at this point. */ plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n", id->length, id->value); #endif if (gssapi_gss2vmbuf(id, &vmbuf) < 0) { plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n"); maj_stat = gss_release_buffer(&min_stat, id); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release id buffer\n"); return NULL; } maj_stat = gss_release_buffer(&min_stat, id); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release id buffer\n"); return vmbuf; }
/* * parse a conn section */ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg) { char *conn_name = (conn->name == NULL)? "%default":conn->name; for ( ; kw; kw = kw->next) { bool assigned = FALSE; kw_token_t token = kw->entry->token; if (token >= KW_LEFT_FIRST && token <= KW_LEFT_LAST) { kw_end(conn, &conn->left, token - KW_LEFT_FIRST + KW_END_FIRST , kw, conn_name, cfg); continue; } else if (token >= KW_RIGHT_FIRST && token <= KW_RIGHT_LAST) { kw_end(conn, &conn->right, token - KW_RIGHT_FIRST + KW_END_FIRST , kw, conn_name, cfg); continue; } if (token == KW_AUTO) { token = KW_CONN_SETUP; } else if (token == KW_ALSO) { if (cfg->parse_also) { also_t *also = malloc_thing(also_t); also->name = clone_str(kw->value); also->next = conn->also; conn->also = also; DBG(DBG_CONTROL, DBG_log(" also=%s", kw->value) ) } continue; } if (token < KW_CONN_FIRST || token > KW_CONN_LAST) { plog("# unsupported keyword '%s' in conn '%s'" , kw->entry->name, conn_name); cfg->err++; continue; } if (!assign_arg(token, KW_CONN_FIRST, kw, (char *)conn, &assigned)) { plog(" bad argument value in conn '%s'", conn_name); cfg->err++; continue; } if (assigned) continue; switch (token) { case KW_TYPE: conn->policy &= ~(POLICY_TUNNEL | POLICY_SHUNT_MASK); if (streq(kw->value, "tunnel")) { conn->policy |= POLICY_TUNNEL; } else if (streq(kw->value, "beet")) { conn->policy |= POLICY_BEET; } else if (streq(kw->value, "transport_proxy")) { conn->policy |= POLICY_PROXY; } else if (streq(kw->value, "passthrough") || streq(kw->value, "pass")) { conn->policy |= POLICY_SHUNT_PASS; } else if (streq(kw->value, "drop")) { conn->policy |= POLICY_SHUNT_DROP; } else if (streq(kw->value, "reject")) { conn->policy |= POLICY_SHUNT_REJECT; } else if (strcmp(kw->value, "transport") != 0) { plog("# bad policy value: %s=%s", kw->entry->name, kw->value); cfg->err++; } break; case KW_PFS: KW_POLICY_FLAG("yes", "no", POLICY_PFS) break; case KW_COMPRESS: KW_POLICY_FLAG("yes", "no", POLICY_COMPRESS) break; case KW_PMTUDISC: if (streq(kw->value, "no")) { conn->xfrm_flags |= XFRM_STATE_NOPMTUDISC; } break; case KW_IPSECDEV: conn->dev = get_ifindex(kw->value); if (conn->dev < 0) { cfg->err++; } break; case KW_ECN: if (streq(kw->value, "no")) { conn->xfrm_flags |= XFRM_STATE_NOECN; } break; case KW_AUTH: KW_POLICY_FLAG("ah", "esp", POLICY_AUTHENTICATE) break; case KW_AUTHBY: conn->policy &= ~(POLICY_ID_AUTH_MASK | POLICY_ENCRYPT); if (!(streq(kw->value, "never") || streq(kw->value, "eap"))) { char *value = kw->value; char *second = strchr(kw->value, '|'); if (second != NULL) { *second = '\0'; } /* also handles the cases secret|rsasig and rsasig|secret */ for (;;) { if (streq(value, "rsa") || streq(value, "rsasig") || streq(value, "ecdsa") || streq(value, "ecdsasig") || streq(value, "pubkey")) { conn->policy |= POLICY_PUBKEY | POLICY_ENCRYPT; } else if (streq(value, "secret") || streq(value, "psk")) { conn->policy |= POLICY_PSK | POLICY_ENCRYPT; } else if (streq(value, "xauthrsasig")) { conn->policy |= POLICY_XAUTH_RSASIG | POLICY_ENCRYPT; } else if (streq(value, "xauthpsk")) { conn->policy |= POLICY_XAUTH_PSK | POLICY_ENCRYPT; } else { plog("# bad policy value: %s=%s", kw->entry->name, kw->value); cfg->err++; break; } if (second == NULL) { break; } value = second; second = NULL; /* traverse the loop no more than twice */ } } break; case KW_EAP: { char *sep; /* check for vendor-type format */ sep = strchr(kw->value, '-'); if (sep) { *(sep++) = '\0'; conn->eap_type = atoi(kw->value); conn->eap_vendor = atoi(sep); if (conn->eap_type == 0 || conn->eap_vendor == 0) { plog("# invalid EAP type: %s=%s", kw->entry->name, kw->value); cfg->err++; } break; } if (streq(kw->value, "aka")) { conn->eap_type = 23; } else if (streq(kw->value, "sim")) { conn->eap_type = 18; } else if (streq(kw->value, "md5")) { conn->eap_type = 4; } else if (streq(kw->value, "gtc")) { conn->eap_type = 6; } else if (streq(kw->value, "mschapv2")) { conn->eap_type = 26; } else if (streq(kw->value, "radius")) { /* pseudo-type */ conn->eap_type = 253; } else { conn->eap_type = atoi(kw->value); if (conn->eap_type == 0) { plog("# unknown EAP type: %s=%s", kw->entry->name, kw->value); cfg->err++; } } break; } case KW_KEYINGTRIES: if (streq(kw->value, "%forever")) { conn->sa_keying_tries = 0; } else { char *endptr; conn->sa_keying_tries = strtoul(kw->value, &endptr, 10); if (*endptr != '\0') { plog("# bad integer value: %s=%s", kw->entry->name, kw->value); cfg->err++; } } break; case KW_REKEY: KW_POLICY_FLAG("no", "yes", POLICY_DONT_REKEY) break; case KW_REAUTH: KW_POLICY_FLAG("no", "yes", POLICY_DONT_REAUTH) break; case KW_MOBIKE: KW_POLICY_FLAG("yes", "no", POLICY_MOBIKE) break; case KW_FORCEENCAPS: KW_POLICY_FLAG("yes", "no", POLICY_FORCE_ENCAP) break; case KW_MODECONFIG: KW_POLICY_FLAG("push", "pull", POLICY_MODECFG_PUSH) break; case KW_XAUTH: KW_POLICY_FLAG("server", "client", POLICY_XAUTH_SERVER) break; default: break; } }
static int gssapi_init(struct ph1handle *iph1) { struct gssapi_ph1_state *gps; gss_buffer_desc id_token, cred_token; gss_buffer_t cred = &cred_token; gss_name_t princ, canon_princ; OM_uint32 maj_stat, min_stat; gps = racoon_calloc(1, sizeof (struct gssapi_ph1_state)); if (gps == NULL) { plog(LLV_ERROR, LOCATION, NULL, "racoon_calloc failed\n"); return -1; } gps->gss_context = GSS_C_NO_CONTEXT; gps->gss_cred = GSS_C_NO_CREDENTIAL; gssapi_set_state(iph1, gps); if (iph1->rmconf->proposal->gssid != NULL) { id_token.length = iph1->rmconf->proposal->gssid->l; id_token.value = iph1->rmconf->proposal->gssid->v; maj_stat = gss_import_name(&min_stat, &id_token, GSS_C_NO_OID, &princ); if (GSS_ERROR(maj_stat)) { gssapi_error(min_stat, LOCATION, "import name\n"); gssapi_free_state(iph1); return -1; } } else gssapi_get_default_name(iph1, 0, &princ); maj_stat = gss_canonicalize_name(&min_stat, princ, GSS_C_NO_OID, &canon_princ); if (GSS_ERROR(maj_stat)) { gssapi_error(min_stat, LOCATION, "canonicalize name\n"); maj_stat = gss_release_name(&min_stat, &princ); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release princ\n"); gssapi_free_state(iph1); return -1; } maj_stat = gss_release_name(&min_stat, &princ); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release princ\n"); maj_stat = gss_export_name(&min_stat, canon_princ, cred); if (GSS_ERROR(maj_stat)) { gssapi_error(min_stat, LOCATION, "export name\n"); maj_stat = gss_release_name(&min_stat, &canon_princ); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release canon_princ\n"); gssapi_free_state(iph1); return -1; } #if 0 /* * XXXJRT Did this debug message ever work? This is a GSS name * blob at this point. */ plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n", cred->length, cred->value); #endif maj_stat = gss_release_buffer(&min_stat, cred); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release cred buffer\n"); maj_stat = gss_acquire_cred(&min_stat, canon_princ, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_BOTH, &gps->gss_cred, NULL, NULL); if (GSS_ERROR(maj_stat)) { gssapi_error(min_stat, LOCATION, "acquire cred\n"); maj_stat = gss_release_name(&min_stat, &canon_princ); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release canon_princ\n"); gssapi_free_state(iph1); return -1; } maj_stat = gss_release_name(&min_stat, &canon_princ); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release canon_princ\n"); return 0; }
int natt_process_natd(struct ikev2_sa *ike_sa, struct ikev2payl_notify *n, int use_spi_r) { unsigned int type; uint8_t *n_data = NULL; rc_vchar_t *hash = NULL; struct sockaddr *addr = NULL; int ret; type = get_notify_type(n); n_data = get_notify_data(n); switch (type) { case IKEV2_NAT_DETECTION_SOURCE_IP: addr = ike_sa->remote; break; case IKEV2_NAT_DETECTION_DESTINATION_IP: addr = ike_sa->local; break; default: plog(PLOG_DEBUG, PLOGLOC, NULL, "invalid notify type\n"); plog(PLOG_DEBUG, PLOGLOC, NULL, "type=%u\n", type); return -1; } hash = natt_create_hash(&ike_sa->index, addr, use_spi_r); if (hash == NULL) { return -1; } ret = memcmp(n_data, hash->v, hash->l); rc_vfree(hash); switch (type) { case IKEV2_NAT_DETECTION_SOURCE_IP: if (ret != 0) { ike_sa->peer_behind_nat = TRUE; } else { ike_sa->peer_behind_nat = FALSE; } break; case IKEV2_NAT_DETECTION_DESTINATION_IP: if (ret != 0) { ike_sa->behind_nat = TRUE; if (ike_sa->natk_timer) { SCHED_KILL(ike_sa->natk_timer); } ike_sa->natk_timer = sched_new(ikev2_natk_interval(ike_sa->rmconf), natt_natk_callback, ike_sa); if (ike_sa->natk_timer == NULL) { plog(PLOG_INTERR, PLOGLOC, NULL, "failed to rc_vmalloc for natk_timer\n"); return -1; } } else { ike_sa->behind_nat = FALSE; } break; default: plog(PLOG_DEBUG, PLOGLOC, NULL, "invalid notify type\n"); plog(PLOG_DEBUG, PLOGLOC, NULL, "type=%d\n", type); return -1; } return 0; }
static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token, kw_list_t *kw, char *conn_name, starter_config_t *cfg) { err_t ugh = NULL; bool assigned = FALSE; bool has_port_wildcard; /* set if port is %any */ char *name = kw->entry->name; char *value = kw->value; if (!assign_arg(token, KW_END_FIRST, kw, (char *)end, &assigned)) goto err; /* post processing of some keywords that were assigned automatically */ switch (token) { case KW_SUBNET: if ((strlen(value) >= 6 && strncmp(value,"vhost:",6) == 0) || (strlen(value) >= 5 && strncmp(value,"vnet:",5) == 0)) { /* used by pluto only */ end->has_virt = TRUE; } else { ip_subnet net; char *pos; int len = 0; end->has_client = TRUE; conn->tunnel_addr_family = ip_version(value); pos = strchr(value, ','); if (pos) { len = pos - value; } ugh = ttosubnet(value, len, ip_version(value), &net); if (ugh != NULL) { plog("# bad subnet: %s=%s [%s]", name, value, ugh); goto err; } } break; case KW_SOURCEIP: if (end->has_natip) { plog("# natip and sourceip cannot be defined at the same time"); goto err; } if (value[0] == '%') { if (streq(value, "%modeconfig") || streq(value, "%modecfg") || streq(value, "%config") || streq(value, "%cfg")) { /* request ip via config payload */ free(end->sourceip); end->sourceip = NULL; end->sourceip_mask = 1; } else { /* %poolname, strip %, serve ip requests */ free(end->sourceip); end->sourceip = clone_str(value+1); end->sourceip_mask = 0; } end->modecfg = TRUE; } else { char *pos; ip_address addr; ip_subnet net; conn->tunnel_addr_family = ip_version(value); pos = strchr(value, '/'); if (pos) { /* CIDR notation, address pool */ ugh = ttosubnet(value, 0, conn->tunnel_addr_family, &net); if (ugh != NULL) { plog("# bad subnet: %s=%s [%s]", name, value, ugh); goto err; } *pos = '\0'; free(end->sourceip); end->sourceip = clone_str(value); end->sourceip_mask = atoi(pos + 1); } else { /* fixed srcip */ ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr); if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); goto err; } end->sourceip_mask = (conn->tunnel_addr_family == AF_INET) ? 32 : 128; } } conn->policy |= POLICY_TUNNEL; break; case KW_SENDCERT: if (end->sendcert == CERT_YES_SEND) { end->sendcert = CERT_ALWAYS_SEND; } else if (end->sendcert == CERT_NO_SEND) { end->sendcert = CERT_NEVER_SEND; } break; default: break; } if (assigned) return; /* individual processing of keywords that were not assigned automatically */ switch (token) { case KW_HOST: if (streq(value, "%defaultroute")) { if (cfg->defaultroute.defined) { end->addr = cfg->defaultroute.addr; end->nexthop = cfg->defaultroute.nexthop; } else if (!cfg->defaultroute.supported) { plog("%%defaultroute not supported, fallback to %%any"); } else { plog("# default route not known: %s=%s", name, value); goto err; } } else if (streq(value, "%any") || streq(value, "%any4")) { anyaddr(conn->addr_family, &end->addr); } else if (streq(value, "%any6")) { conn->addr_family = AF_INET6; anyaddr(conn->addr_family, &end->addr); } else if (streq(value, "%group")) { ip_address any; conn->policy |= POLICY_GROUP | POLICY_TUNNEL; anyaddr(conn->addr_family, &end->addr); anyaddr(conn->tunnel_addr_family, &any); end->has_client = TRUE; } else { /* check for allow_any prefix */ if (value[0] == '%') { end->allow_any = TRUE; value++; } conn->addr_family = ip_version(value); ugh = ttoaddr(value, 0, conn->addr_family, &end->addr); if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); if (streq(ugh, "does not look numeric and name lookup failed")) { end->dns_failed = TRUE; anyaddr(conn->addr_family, &end->addr); } else { goto err; } } } break; case KW_NEXTHOP: if (streq(value, "%defaultroute")) { if (cfg->defaultroute.defined) { end->nexthop = cfg->defaultroute.nexthop; } else { plog("# default route not known: %s=%s", name, value); goto err; } } else if (streq(value, "%direct")) { ugh = anyaddr(conn->addr_family, &end->nexthop); } else { conn->addr_family = ip_version(value); ugh = ttoaddr(value, 0, conn->addr_family, &end->nexthop); } if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); goto err; } break; case KW_SUBNETWITHIN: { ip_subnet net; end->has_client = TRUE; end->has_client_wildcard = TRUE; conn->tunnel_addr_family = ip_version(value); ugh = ttosubnet(value, 0, ip_version(value), &net); if (ugh != NULL) { plog("# bad subnet: %s=%s [%s]", name, value, ugh); goto err; } end->subnet = clone_str(value); break; } case KW_PROTOPORT: ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &has_port_wildcard); end->has_port_wildcard = has_port_wildcard; break; case KW_NATIP: if (end->sourceip) { plog("# natip and sourceip cannot be defined at the same time"); goto err; } if (streq(value, "%defaultroute")) { char buf[64]; if (cfg->defaultroute.defined) { addrtot(&cfg->defaultroute.addr, 0, buf, sizeof(buf)); end->sourceip = clone_str(buf); } else { plog("# default route not known: %s=%s", name, value); goto err; } } else { ip_address addr; conn->tunnel_addr_family = ip_version(value); ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr); if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); goto err; } end->sourceip = clone_str(value); } end->has_natip = TRUE; conn->policy |= POLICY_TUNNEL; break; default: break; } return; err: plog(" bad argument value in conn '%s'", conn_name); cfg->err++; }
/* * Try to locate a key using NIS+. */ int nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp) { nis_result *result; int error = 0; struct nisplus_search_callback_data data; nis_name index; char *org; /* if map does not have ".org_dir" then append it */ size_t l; org = strstr(map, NISPLUS_ORGDIR); if (org == NULL) org = NISPLUS_ORGDIR; else org = ""; /* make some room for the NIS index */ l = sizeof('[') /* for opening selection criteria */ + sizeof(NISPLUS_KEY) + strlen(key) + sizeof(']') /* for closing selection criteria */ + sizeof(',') /* + 1 for , separator */ + strlen(map) + sizeof(NISPLUS_ORGDIR); index = xmalloc(l); if (index == NULL) { plog(XLOG_ERROR, "Unable to create index %s: %s", map, strerror(ENOMEM)); return ENOMEM; } xsnprintf(index, l, "[%s%s],%s%s", NISPLUS_KEY, key, map, org); data.key = key; data.value = NULL; dlog("NISplus search for %s", index); result = nis_list(index, EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH, (int (*)()) nisplus_search_callback, &data); /* free off the NIS index */ XFREE(index); if (result == NULL) { plog(XLOG_ERROR, "nisplus_search: %s: %s", map, strerror(ENOMEM)); return ENOMEM; } /* * Do something interesting with the return code */ switch (result->status) { case NIS_SUCCESS: case NIS_CBRESULTS: if (data.value == NULL) { nis_object *value = result->objects.objects_val; dlog("NISplus search found <nothing>"); dlog("NISplus search for %s: %s(%d)", map, nis_sperrno(result->status), result->status); if (value != NULL) data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1)); } if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) { *val = sun_entry2amd(key, data.value); XFREE(data.value); /* strnsave malloc'ed it above */ } else *val = data.value; if (*val) { error = 0; dlog("NISplus search found %s", *val); } else { error = ENOENT; dlog("NISplus search found nothing"); } *tp = 0; break; case NIS_NOSUCHNAME: dlog("NISplus search returned %d", result->status); error = ENOENT; break; default: plog(XLOG_ERROR, "nisplus_search: %s: %s", map, nis_sperrno(result->status)); error = EIO; break; } nis_freeresult(result); return error; }
/* * Return the home directory pathname for the user with uid "userid". */ char * homedir(int userid, int groupid) { static char linkval[MAXPATHLEN + 1]; static struct timeval tp; uid2home_t *found; char *homename; struct stat homestat; int old_groupid, old_userid; clock_valid = 0; /* invalidate logging clock */ if ((found = plt_search(userid)) == (uid2home_t *) NULL) { return alt_spooldir; /* use alt spool for unknown uid */ } homename = found->home; if (homename[0] != '/' || homename[1] == '\0') { found->last_status = 1; return alt_spooldir; /* use alt spool for / or rel. home */ } if ((int) userid == 0) /* force all uid 0 to use root's home */ sprintf(linkval, "%s/%s", root_home, home_subdir); else sprintf(linkval, "%s/%s", homename, home_subdir); if (noverify) { found->last_status = 0; return linkval; } /* * To optimize hlfsd, we don't actually check the validity of the * symlink if it has been checked in the last N seconds. It is * very likely that the link, machine, and filesystem are still * valid, as long as N is small. But if N is large, that may not be * true. That's why the default N is 5 minutes, but we allow the * user to override this value via a command line option. Note that * we do not update the last_access_time each time it is accessed, * but only once every N seconds. */ if (gettimeofday(&tp, (struct timezone *) NULL) < 0) { tp.tv_sec = 0; } else { if ((tp.tv_sec - found->last_access_time) < cache_interval) { if (found->last_status == 0) { return linkval; } else { return alt_spooldir; } } else { found->last_access_time = tp.tv_sec; } } #ifdef DEBUG /* * only run this forking code if asked for -D fork * or if did not ask for -D nofork */ amuDebug(D_FORK) { #endif /* DEBUG */ /* fork child to process request if none in progress */ if (found->child && kill(found->child, 0)) found->child = 0; if (found->child) delay(found, 5); /* wait a bit if in progress */ if (found->child) { /* better safe than sorry - maybe */ found->last_status = 1; return alt_spooldir; } if ((found->child = fork()) < 0) { found->last_status = 1; return alt_spooldir; } if (found->child) { /* PARENT */ #ifdef DEBUG if (lastchild) plog(XLOG_INFO, "cache spill uid = %ld, pid = %ld, home = %s", (long) lastchild->uid, (long) lastchild->child, lastchild->home); #endif /* DEBUG */ lastchild = found; return (char *) NULL; /* return NULL to parent, so it can continue */ } #ifdef DEBUG } /* end of Debug(D_FORK) */ #endif /* DEBUG */ /* * CHILD: (or parent if -D nofork) * * Check and create dir if needed. * Check disk space and/or quotas too. * * We don't need to set the _last_status field of found after the fork * in the child, b/c that information would be later determined in * nfsproc_readlink_2() and the correct exit status would be returned * to the parent upon SIGCHLD in interlock(). * */ am_set_mypid(); /* for logging routines */ if ((old_groupid = setgid(groupid)) < 0) { plog(XLOG_WARNING, "could not setgid to %d: %m", groupid); return linkval; } if ((old_userid = seteuid(userid)) < 0) { plog(XLOG_WARNING, "could not seteuid to %d: %m", userid); setgid(old_groupid); return linkval; } if (hlfsd_stat(linkval, &homestat) < 0) { if (errno == ENOENT) { /* make the spool dir if possible */ /* don't use recursive mkdirs here */ if (mkdir(linkval, PERS_SPOOLMODE) < 0) { seteuid(old_userid); setgid(old_groupid); plog(XLOG_WARNING, "can't make directory %s: %m", linkval); return alt_spooldir; } /* fall through to testing the disk space / quota */ } else { /* the home dir itself must not exist then */ seteuid(old_userid); setgid(old_groupid); plog(XLOG_WARNING, "bad link to %s: %m", linkval); return alt_spooldir; } } /* * If gets here, then either the spool dir in the home dir exists, * or it was just created. In either case, we now need to * test if we can create a small file and write at least one * byte into it. This will test that we have both enough inodes * and disk blocks to spare, or they fall within the user's quotas too. * We are still seteuid to the user at this point. */ if (hlfsd_diskspace(linkval) < 0) { seteuid(old_userid); setgid(old_groupid); plog(XLOG_WARNING, "no more space in %s: %m", linkval); return alt_spooldir; } else { seteuid(old_userid); setgid(old_groupid); return linkval; } }
/* perform record reading/parsing of individual passwd database records */ static struct passwd * hlfsd_getpwent(void) { char buf[256], *cp; /* check if to perform standard unix function */ if (!passwdfile) { return getpwent(); } clock_valid = 0; /* invalidate logging clock */ /* return here to read another entry */ readent: /* return NULL if reached end of file */ if (feof(passwd_fp)) return NULL; pw_name[0] = pw_dir[0] = '\0'; /* read records */ buf[0] = '\0'; fgets(buf, 256, passwd_fp); passwd_line++; if (!buf || buf[0] == '\0') goto readent; /* read user name */ cp = strtok(buf, ":"); if (!cp || cp[0] == '\0') { plog(XLOG_ERROR, "no user name on line %d of %s", passwd_line, passwdfile); goto readent; } strcpy(pw_name, cp); /* will show up in passwd_ent.pw_name */ /* skip passwd */ strtok(NULL, ":"); /* read uid */ cp = strtok(NULL, ":"); if (!cp || cp[0] == '\0') { plog(XLOG_ERROR, "no uid on line %d of %s", passwd_line, passwdfile); goto readent; } passwd_ent.pw_uid = atoi(cp); /* skip gid and gcos */ strtok(NULL, ":"); strtok(NULL, ":"); /* read home dir */ cp = strtok(NULL, ":"); if (!cp || cp[0] == '\0') { plog(XLOG_ERROR, "no home dir on line %d of %s", passwd_line, passwdfile); goto readent; } strcpy(pw_dir, cp); /* will show up in passwd_ent.pw_dir */ /* the rest of the fields are unimportant and not being considered */ plog(XLOG_USER, "hlfsd_getpwent: name=%s, uid=%ld, dir=%s", passwd_ent.pw_name, (long) passwd_ent.pw_uid, passwd_ent.pw_dir); return &passwd_ent; }
int autofs_mount_fs(am_node *mp, mntfs *mf) { char *target, *target2 = NULL; int err = 0; if (mf->mf_flags & MFF_ON_AUTOFS) { if ((err = mkdir(mp->am_path, 0555))) return errno; } /* * For sublinks, we could end up here with an already mounted f/s. * Don't do anything in that case. */ if (!(mf->mf_flags & MFF_MOUNTED)) err = mf->mf_ops->mount_fs(mp, mf); if (err) { if (mf->mf_flags & MFF_ON_AUTOFS) rmdir(mp->am_path); return err; } if (mf->mf_flags & MFF_ON_AUTOFS) /* Nothing else to do */ return 0; if (mp->am_link) target = mp->am_link; else target = mf->mf_fo->opt_fs; #ifdef MNT2_GEN_OPT_BIND if (bind_works && gopt.flags & CFM_AUTOFS_USE_LOFS) { struct stat buf; /* * HACK ALERT! * * Since the bind mount mechanism doesn't allow mountpoint crossing, * we _must_ use symlinks for the host mount case. Otherwise we end up * with a bunch of empty mountpoints... */ if (mf->mf_ops == &amfs_host_ops) goto use_symlink; if (target[0] != '/') target2 = str3cat(NULL, mp->am_parent->am_path, "/", target); else target2 = strdup(target); /* * We need to stat() the destination, because the bind mount does not * follow symlinks and/or allow for non-existent destinations. * We fall back to symlinks if there are problems. * * We also need to temporarily change pgrp, otherwise our stat() won't * trigger whatever cascading mounts are needed. * * WARNING: we will deadlock if this function is called from the master * amd process and it happens to trigger another auto mount. Therefore, * this function should be called only from a child amd process, or * at the very least it should not be called from the parent unless we * know for sure that it won't cause a recursive mount. We refuse to * cause the recursive mount anyway if called from the parent amd. */ if (!foreground) { pid_t pgrp = getpgrp(); setpgrp(); err = stat(target2, &buf); if ((err = setpgid(0, pgrp))) { plog(XLOG_ERROR, "autofs: cannot restore pgrp: %s", strerror(errno)); plog(XLOG_ERROR, "autofs: aborting the mount"); goto out; } if (err) goto use_symlink; } if ((err = lstat(target2, &buf))) goto use_symlink; if (S_ISLNK(buf.st_mode)) goto use_symlink; plog(XLOG_INFO, "autofs: bind-mounting %s -> %s", mp->am_path, target2); mkdir(mp->am_path, 0555); err = mount_lofs(mp->am_path, target2, mf->mf_mopts, 1); if (err) { rmdir(mp->am_path); plog(XLOG_INFO, "autofs: bind-mounting %s -> %s failed", mp->am_path, target2); goto use_symlink; } goto out; } #endif /* MNT2_GEN_OPT_BIND */ use_symlink: plog(XLOG_INFO, "autofs: symlinking %s -> %s", mp->am_path, target); err = symlink(target, mp->am_path); out: if (target2) XFREE(target2); if (err) return errno; return 0; }
/* * Handle an amd restart. * * Scan through the mount list finding all "interesting" mount points. * Next hack up partial data structures and add the mounted file * system to the list of known filesystems. This will leave a * dangling reference to that filesystems, so when the filesystem is * finally inherited, an extra "free" must be done on it. * * This module relies on internal details of other components. If * you change something else make *sure* restart() still works. */ void restart(void) { /* * Read the existing mount table */ mntlist *ml, *mlp; /* * For each entry, find nfs, ufs or auto mounts * and create a partial am_node to represent it. */ for (mlp = ml = read_mtab("restart", mnttab_file_name); mlp; mlp = mlp->mnext) { mntent_t *me = mlp->mnt; am_ops *fs_ops = 0; if (STREQ(me->mnt_type, MNTTAB_TYPE_UFS)) { /* * UFS entry */ fs_ops = &ufs_ops; } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) { /* * NFS entry, or possibly an Amd entry... * The mnt_fsname for daemon mount points is * host:(pidXXX) * or (seen on Solaris) * host:daemon(pidXXX) */ char *colon = strchr(me->mnt_fsname, ':'); if (colon && strstr(colon, "(pid")) { plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir); fs_ops = &amfs_link_ops; } else { fs_ops = &nfs_ops; } #ifdef MNTTAB_TYPE_NFS3 } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS3)) { fs_ops = &nfs_ops; #endif /* MNTTAB_TYPE_NFS3 */ #ifdef MNTTAB_TYPE_LOFS } else if (STREQ(me->mnt_type, MNTTAB_TYPE_LOFS)) { fs_ops = &lofs_ops; #endif /* MNTTAB_TYPE_LOFS */ #ifdef MNTTAB_TYPE_CDFS } else if (STREQ(me->mnt_type, MNTTAB_TYPE_CDFS)) { fs_ops = &cdfs_ops; #endif /* MNTTAB_TYPE_CDFS */ #ifdef MNTTAB_TYPE_PCFS } else if (STREQ(me->mnt_type, MNTTAB_TYPE_PCFS)) { fs_ops = &pcfs_ops; #endif /* MNTTAB_TYPE_PCFS */ #ifdef MNTTAB_TYPE_MFS } else if (STREQ(me->mnt_type, MNTTAB_TYPE_MFS)) { /* * MFS entry. Fake with a symlink. */ fs_ops = &amfs_link_ops; #endif /* MNTTAB_TYPE_MFS */ } else { /* * Catch everything else with symlinks to * avoid recursive mounts. This is debatable... */ fs_ops = &amfs_link_ops; } /* * If we found something to do */ if (fs_ops) { mntfs *mf; am_opts mo; char *cp; cp = strchr(me->mnt_fsname, ':'); /* * Partially fake up an opts structure */ memset(&mo, 0, sizeof(mo)); mo.opt_rhost = 0; mo.opt_rfs = 0; if (cp) { *cp = '\0'; mo.opt_rhost = strdup(me->mnt_fsname); mo.opt_rfs = strdup(cp + 1); *cp = ':'; } else if (fs_ops->ffserver == find_nfs_srvr) { /* * Prototype 4.4 BSD used to end up here - * might as well keep the workaround for now */ plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname); mo.opt_rhost = strdup(me->mnt_fsname); mo.opt_rfs = strdup("/"); me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/"); } mo.opt_fs = me->mnt_dir; mo.opt_opts = me->mnt_opts; /* * Make a new mounted filesystem */ mf = find_mntfs(fs_ops, &mo, me->mnt_dir, me->mnt_fsname, "", me->mnt_opts, ""); if (mf->mf_refc == 1) { mf->mf_flags |= MFF_RESTART | MFF_MOUNTED; mf->mf_error = 0; /* Already mounted correctly */ mf->mf_fo = 0; /* * If the restarted type is a link then * don't time out. */ if (fs_ops == &amfs_link_ops || fs_ops == &ufs_ops) mf->mf_flags |= MFF_RSTKEEP; if (fs_ops->fs_init) { /* * Don't care whether this worked since * it is checked again when the fs is * inherited. */ (void) (*fs_ops->fs_init) (mf); } plog(XLOG_INFO, "%s restarted fstype %s on %s", me->mnt_fsname, fs_ops->fs_type, me->mnt_dir); } else { /* Something strange happened - two mounts at the same place! */ free_mntfs(mf); } /* * Clean up mo */ if (mo.opt_rhost) XFREE(mo.opt_rhost); if (mo.opt_rfs) XFREE(mo.opt_rfs); } } /* * Free the mount list */ free_mntlist(ml); }