/* * Non-nsswitch.conf version with hard-coded order. */ struct sudo_nss_list * sudo_read_nss(void) { static struct sudo_nss_list snl; # ifdef HAVE_LDAP tq_append(&snl, &sudo_nss_ldap); # endif tq_append(&snl, &sudo_nss_file); return &snl; }
/* * Read in /etc/nsswitch.conf * Returns a tail queue of matches. */ struct sudo_nss_list * sudo_read_nss(void) { FILE *fp; char *cp; int saw_files = FALSE; int saw_ldap = FALSE; int got_match = FALSE; static struct sudo_nss_list snl; if ((fp = fopen(_PATH_NSSWITCH_CONF, "r")) == NULL) goto nomatch; while ((cp = sudo_parseln(fp)) != NULL) { /* Skip blank or comment lines */ if (*cp == '\0') continue; /* Look for a line starting with "sudoers:" */ if (strncasecmp(cp, "sudoers:", 8) != 0) continue; /* Parse line */ for ((cp = strtok(cp + 8, " \t")); cp != NULL; (cp = strtok(NULL, " \t"))) { if (strcasecmp(cp, "files") == 0 && !saw_files) { tq_append(&snl, &sudo_nss_file); got_match = TRUE; } else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) { tq_append(&snl, &sudo_nss_ldap); got_match = TRUE; } else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) { /* NOTFOUND affects the most recent entry */ tq_last(&snl)->ret_if_notfound = TRUE; got_match = FALSE; } else got_match = FALSE; } /* Only parse the first "sudoers:" line */ break; } fclose(fp); nomatch: /* Default to files only if no matches */ if (tq_empty(&snl)) tq_append(&snl, &sudo_nss_file); return &snl; }
void digi_regen (int from_chan, packet_t pp) { int to_chan; packet_t result; // dw_printf ("digi_regen()\n"); assert (from_chan >= 0 && from_chan < MAX_CHANS); for (to_chan=0; to_chan<MAX_CHANS; to_chan++) { if (save_digi_config_p->regen[from_chan][to_chan]) { result = ax25_dup (pp); if (result != NULL) { // TODO: if AX.25 and has been digipeated, put in HI queue? tq_append (to_chan, TQ_PRIO_1_LO, result); } } } } /* end dig_regen */
void digipeater (int from_chan, packet_t pp) { int to_chan; // dw_printf ("digipeater()\n"); assert (from_chan >= 0 && from_chan < MAX_CHANS); if ( ! save_audio_config_p->achan[from_chan].valid) { text_color_set(DW_COLOR_ERROR); dw_printf ("digipeater: Did not expect to receive on invalid channel %d.\n", from_chan); } /* * First pass: Look at packets being digipeated to same channel. * * We want these to get out quickly. */ for (to_chan=0; to_chan<MAX_CHANS; to_chan++) { if (save_digi_config_p->enabled[from_chan][to_chan]) { if (to_chan == from_chan) { packet_t result; result = digipeat_match (from_chan, pp, save_audio_config_p->achan[from_chan].mycall, save_audio_config_p->achan[to_chan].mycall, &save_digi_config_p->alias[from_chan][to_chan], &save_digi_config_p->wide[from_chan][to_chan], to_chan, save_digi_config_p->preempt[from_chan][to_chan], save_digi_config_p->filter_str[from_chan][to_chan]); if (result != NULL) { dedupe_remember (pp, to_chan); tq_append (to_chan, TQ_PRIO_0_HI, result); } } } } /* * Second pass: Look at packets being digipeated to different channel. * * These are lower priority */ for (to_chan=0; to_chan<MAX_CHANS; to_chan++) { if (save_digi_config_p->enabled[from_chan][to_chan]) { if (to_chan != from_chan) { packet_t result; result = digipeat_match (from_chan, pp, save_audio_config_p->achan[from_chan].mycall, save_audio_config_p->achan[to_chan].mycall, &save_digi_config_p->alias[from_chan][to_chan], &save_digi_config_p->wide[from_chan][to_chan], to_chan, save_digi_config_p->preempt[from_chan][to_chan], save_digi_config_p->filter_str[from_chan][to_chan]); if (result != NULL) { dedupe_remember (pp, to_chan); tq_append (to_chan, TQ_PRIO_1_LO, result); } } } } } /* end digipeater */
/* * Read in /etc/netsvc.conf (like nsswitch.conf on AIX) * Returns a tail queue of matches. */ struct sudo_nss_list * sudo_read_nss(void) { FILE *fp; char *cp, *ep; int saw_files = FALSE; int saw_ldap = FALSE; int got_match = FALSE; static struct sudo_nss_list snl; if ((fp = fopen(_PATH_NETSVC_CONF, "r")) == NULL) goto nomatch; while ((cp = sudo_parseln(fp)) != NULL) { /* Skip blank or comment lines */ if (*cp == '\0') continue; /* Look for a line starting with "sudoers = " */ if (strncasecmp(cp, "sudoers", 7) != 0) continue; cp += 7; while (isspace((unsigned char)*cp)) cp++; if (*cp++ != '=') continue; /* Parse line */ for ((cp = strtok(cp, ",")); cp != NULL; (cp = strtok(NULL, ","))) { /* Trim leading whitespace. */ while (isspace((unsigned char)*cp)) cp++; if (!saw_files && strncasecmp(cp, "files", 5) == 0 && (isspace((unsigned char)cp[5]) || cp[5] == '\0')) { tq_append(&snl, &sudo_nss_file); got_match = TRUE; ep = &cp[5]; } else if (!saw_ldap && strncasecmp(cp, "ldap", 4) == 0 && (isspace((unsigned char)cp[4]) || cp[4] == '\0')) { tq_append(&snl, &sudo_nss_ldap); got_match = TRUE; ep = &cp[4]; } else { got_match = FALSE; } /* check for = auth qualifier */ if (got_match && *ep) { cp = ep; while (isspace((unsigned char)*cp) || *cp == '=') cp++; if (strncasecmp(cp, "auth", 4) == 0 && (isspace((unsigned char)cp[4]) || cp[4] == '\0')) { tq_last(&snl)->ret_if_found = TRUE; } } } /* Only parse the first "sudoers" line */ break; } fclose(fp); nomatch: /* Default to files only if no matches */ if (tq_empty(&snl)) tq_append(&snl, &sudo_nss_file); return &snl; }
static void * beacon_thread (void *arg) #endif { int j; time_t earliest; time_t now; /* * Information from GPS. */ int fix = 0; /* 0 = none, 2 = 2D, 3 = 3D */ double my_lat = 0; /* degrees */ double my_lon = 0; float my_course = 0; /* degrees */ float my_speed_knots = 0; float my_speed_mph = 0; float my_alt = 0; /* meters */ /* * SmartBeaconing state. */ time_t sb_prev_time = 0; /* Time of most recent transmission. */ float sb_prev_course = 0; /* Most recent course reported. */ //float sb_prev_speed_mph; /* Most recent speed reported. */ int sb_every; /* Calculated time between transmissions. */ #if DEBUG struct tm tm; char hms[20]; now = time(NULL); localtime_r (&now, &tm); strftime (hms, sizeof(hms), "%H:%M:%S", &tm); text_color_set(DW_COLOR_DEBUG); dw_printf ("beacon_thread: started %s\n", hms); #endif now = time(NULL); while (1) { assert (g_misc_config_p->num_beacons >= 1); /* * Sleep until time for the earliest scheduled or * the soonest we could transmit due to corner pegging. */ earliest = g_misc_config_p->beacon[0].next; for (j=1; j<g_misc_config_p->num_beacons; j++) { if (g_misc_config_p->beacon[j].btype == BEACON_IGNORE) continue; earliest = MIN(g_misc_config_p->beacon[j].next, earliest); } if (g_misc_config_p->sb_configured && g_using_gps) { earliest = MIN(now + g_misc_config_p->sb_turn_time, earliest); earliest = MIN(now + g_misc_config_p->sb_fast_rate, earliest); } if (earliest > now) { SLEEP_SEC (earliest - now); } /* * Woke up. See what needs to be done. */ now = time(NULL); #if DEBUG localtime_r (&now, &tm); strftime (hms, sizeof(hms), "%H:%M:%S", &tm); text_color_set(DW_COLOR_DEBUG); dw_printf ("beacon_thread: woke up %s\n", hms); #endif /* * Get information from GPS if being used. * This needs to be done before the next scheduled tracker * beacon because corner pegging make it sooner. */ #if DEBUG_SIM FILE *fp; char cs[40]; fp = fopen ("c:\\cygwin\\tmp\\cs", "r"); if (fp != NULL) { fscanf (fp, "%f %f", &my_course, &my_speed_knots); fclose (fp); } else { fprintf (stderr, "Can't read /tmp/cs.\n"); } fix = 3; my_speed_mph = KNOTS_TO_MPH * my_speed_knots; my_lat = 42.99; my_lon = 71.99; my_alt = 100; #else if (g_using_gps) { fix = dwgps_read (&my_lat, &my_lon, &my_speed_knots, &my_course, &my_alt); my_speed_mph = KNOTS_TO_MPH * my_speed_knots; /* Don't complain here for no fix. */ /* Possibly at the point where about to transmit. */ } #endif /* * Run SmartBeaconing calculation if configured and GPS data available. */ if (g_misc_config_p->sb_configured && g_using_gps && fix >= 2) { if (my_speed_mph > g_misc_config_p->sb_fast_speed) { sb_every = g_misc_config_p->sb_fast_rate; } else if (my_speed_mph < g_misc_config_p->sb_slow_speed) { sb_every = g_misc_config_p->sb_slow_rate; } else { /* Can't divide by 0 assuming sb_slow_speed > 0. */ sb_every = ( g_misc_config_p->sb_fast_rate * g_misc_config_p->sb_fast_speed ) / my_speed_mph; } #if DEBUG_SIM text_color_set(DW_COLOR_DEBUG); dw_printf ("SB: fast %d %d slow %d %d speed=%.1f every=%d\n", g_misc_config_p->sb_fast_speed, g_misc_config_p->sb_fast_rate, g_misc_config_p->sb_slow_speed, g_misc_config_p->sb_slow_rate, my_speed_mph, sb_every); #endif /* * Test for "Corner Pegging" if moving. */ if (my_speed_mph >= 1.0) { int turn_threshold = g_misc_config_p->sb_turn_angle + g_misc_config_p->sb_turn_slope / my_speed_mph; #if DEBUG_SIM text_color_set(DW_COLOR_DEBUG); dw_printf ("SB-moving: course %.0f prev %.0f thresh %d\n", my_course, sb_prev_course, turn_threshold); #endif if (heading_change(my_course, sb_prev_course) > turn_threshold && now >= sb_prev_time + g_misc_config_p->sb_turn_time) { /* Send it now. */ for (j=0; j<g_misc_config_p->num_beacons; j++) { if (g_misc_config_p->beacon[j].btype == BEACON_TRACKER) { g_misc_config_p->beacon[j].next = now; } } } /* significant change in direction */ } /* is moving */ } /* apply SmartBeaconing */ for (j=0; j<g_misc_config_p->num_beacons; j++) { if (g_misc_config_p->beacon[j].btype == BEACON_IGNORE) continue; if (g_misc_config_p->beacon[j].next <= now) { int strict = 1; /* Strict packet checking because they will go over air. */ char stemp[20]; char info[AX25_MAX_INFO_LEN]; char beacon_text[AX25_MAX_PACKET_LEN]; packet_t pp = NULL; char mycall[AX25_MAX_ADDR_LEN]; /* * Obtain source call for the beacon. * This could potentially be different on different channels. * When sending to IGate server, use call from first radio channel. * * Check added in version 1.0a. Previously used index of -1. */ strcpy (mycall, "NOCALL"); if (g_misc_config_p->beacon[j].chan == -1) { strcpy (mycall, g_digi_config_p->mycall[0]); } else { strcpy (mycall, g_digi_config_p->mycall[g_misc_config_p->beacon[j].chan]); } if (strlen(mycall) == 0 || strcmp(mycall, "NOCALL") == 0) { text_color_set(DW_COLOR_ERROR); dw_printf ("MYCALL not set for beacon in config file line %d.\n", g_misc_config_p->beacon[j].lineno); continue; } /* * Prepare the monitor format header. */ strcpy (beacon_text, mycall); strcat (beacon_text, ">"); sprintf (stemp, "%s%1d%1d", APP_TOCALL, MAJOR_VERSION, MINOR_VERSION); strcat (beacon_text, stemp); if (g_misc_config_p->beacon[j].via) { strcat (beacon_text, ","); strcat (beacon_text, g_misc_config_p->beacon[j].via); } strcat (beacon_text, ":"); /* * Add the info part depending on beacon type. */ switch (g_misc_config_p->beacon[j].btype) { case BEACON_POSITION: encode_position (g_misc_config_p->beacon[j].compress, g_misc_config_p->beacon[j].lat, g_misc_config_p->beacon[j].lon, g_misc_config_p->beacon[j].symtab, g_misc_config_p->beacon[j].symbol, g_misc_config_p->beacon[j].power, g_misc_config_p->beacon[j].height, g_misc_config_p->beacon[j].gain, g_misc_config_p->beacon[j].dir, 0, 0, /* course, speed */ g_misc_config_p->beacon[j].freq, g_misc_config_p->beacon[j].tone, g_misc_config_p->beacon[j].offset, g_misc_config_p->beacon[j].comment, info); strcat (beacon_text, info); g_misc_config_p->beacon[j].next = now + g_misc_config_p->beacon[j].every; break; case BEACON_OBJECT: encode_object (g_misc_config_p->beacon[j].objname, g_misc_config_p->beacon[j].compress, 0, g_misc_config_p->beacon[j].lat, g_misc_config_p->beacon[j].lon, g_misc_config_p->beacon[j].symtab, g_misc_config_p->beacon[j].symbol, g_misc_config_p->beacon[j].power, g_misc_config_p->beacon[j].height, g_misc_config_p->beacon[j].gain, g_misc_config_p->beacon[j].dir, 0, 0, /* course, speed */ g_misc_config_p->beacon[j].freq, g_misc_config_p->beacon[j].tone, g_misc_config_p->beacon[j].offset, g_misc_config_p->beacon[j].comment, info); strcat (beacon_text, info); g_misc_config_p->beacon[j].next = now + g_misc_config_p->beacon[j].every; break; case BEACON_TRACKER: if (fix >= 2) { int coarse; /* APRS encoder wants 1 - 360. */ /* 0 means none or unknown. */ coarse = (int)roundf(my_course); if (coarse == 0) { coarse = 360; } encode_position (g_misc_config_p->beacon[j].compress, my_lat, my_lon, g_misc_config_p->beacon[j].symtab, g_misc_config_p->beacon[j].symbol, g_misc_config_p->beacon[j].power, g_misc_config_p->beacon[j].height, g_misc_config_p->beacon[j].gain, g_misc_config_p->beacon[j].dir, coarse, (int)roundf(my_speed_knots), g_misc_config_p->beacon[j].freq, g_misc_config_p->beacon[j].tone, g_misc_config_p->beacon[j].offset, g_misc_config_p->beacon[j].comment, info); strcat (beacon_text, info); /* Remember most recent tracker beacon. */ sb_prev_time = now; sb_prev_course = my_course; //sb_prev_speed_mph = my_speed_mph; /* Calculate time for next transmission. */ if (g_misc_config_p->sb_configured) { g_misc_config_p->beacon[j].next = now + sb_every; } else { g_misc_config_p->beacon[j].next = now + g_misc_config_p->beacon[j].every; } } else { g_misc_config_p->beacon[j].next = now + 2; continue; /* No fix. Try again in a couple seconds. */ } break; case BEACON_CUSTOM: if (g_misc_config_p->beacon[j].custom_info != NULL) { strcat (beacon_text, g_misc_config_p->beacon[j].custom_info); } else { text_color_set(DW_COLOR_ERROR); dw_printf ("Internal error. custom_info is null. %s %d\n", __FILE__, __LINE__); continue; } g_misc_config_p->beacon[j].next = now + g_misc_config_p->beacon[j].every; break; case BEACON_IGNORE: default: break; } /* switch beacon type. */ /* * Parse monitor format into form for transmission. */ pp = ax25_from_text (beacon_text, strict); if (pp != NULL) { /* Send to IGate server or radio. */ if (g_misc_config_p->beacon[j].chan == -1) { #if 1 text_color_set(DW_COLOR_XMIT); dw_printf ("[ig] %s\n", beacon_text); #endif igate_send_rec_packet (0, pp); ax25_delete (pp); } else { tq_append (g_misc_config_p->beacon[j].chan, TQ_PRIO_1_LO, pp); } } else { text_color_set(DW_COLOR_ERROR); dw_printf ("Config file: Failed to parse packet constructed from line %d.\n", g_misc_config_p->beacon[j].lineno); dw_printf ("%s\n", beacon_text); } } /* if time to send it */ } /* for each configured beacon */ } /* do forever */ } /* end beacon_thread */
/* * Read in /etc/sudo.conf * Returns a list of plugins. */ static struct plugin_info_list * sudo_read_conf(const char *conf_file) { FILE *fp; char *cp, *name, *path; struct plugin_info *info; static struct plugin_info_list pil; /* XXX */ if ((fp = fopen(conf_file, "r")) == NULL) goto done; while ((cp = sudo_parseln(fp)) != NULL) { /* Skip blank or comment lines */ if (*cp == '\0') continue; /* Look for a line starting with "Path" */ if (strncasecmp(cp, "Path", 4) == 0) { /* Parse line */ if ((name = strtok(cp + 4, " \t")) == NULL || (path = strtok(NULL, " \t")) == NULL) { continue; } if (strcasecmp(name, "askpass") != 0) continue; askpass_path = estrdup(path); continue; } /* Look for a line starting with "Plugin" */ if (strncasecmp(cp, "Plugin", 6) == 0) { /* Parse line */ if ((name = strtok(cp + 6, " \t")) == NULL || (path = strtok(NULL, " \t")) == NULL) { continue; } info = emalloc(sizeof(*info)); info->symbol_name = estrdup(name); info->path = estrdup(path); info->prev = info; info->next = NULL; tq_append(&pil, info); continue; } } fclose(fp); done: if (tq_empty(&pil)) { /* Default policy plugin */ info = emalloc(sizeof(*info)); info->symbol_name = "sudoers_policy"; info->path = SUDOERS_PLUGIN; info->prev = info; info->next = NULL; tq_append(&pil, info); /* Default I/O plugin */ info = emalloc(sizeof(*info)); info->symbol_name = "sudoers_io"; info->path = SUDOERS_PLUGIN; info->prev = info; info->next = NULL; tq_append(&pil, info); } return &pil; }
/* * Load the plugins listed in conf_file. */ void sudo_load_plugins(const char *conf_file, struct plugin_container *policy_plugin, struct plugin_container_list *io_plugins) { struct generic_plugin *plugin; struct plugin_container *container; struct plugin_info *info; struct plugin_info_list *plugin_list; struct stat sb; void *handle; char path[PATH_MAX]; /* Parse sudo.conf */ plugin_list = sudo_read_conf(conf_file); tq_foreach_fwd(plugin_list, info) { if (info->path[0] == '/') { if (strlcpy(path, info->path, sizeof(path)) >= sizeof(path)) errorx(1, "%s: %s", info->path, strerror(ENAMETOOLONG)); } else { if (snprintf(path, sizeof(path), "%s%s", _PATH_SUDO_PLUGIN_DIR, info->path) >= sizeof(path)) { errorx(1, "%s%s: %s", _PATH_SUDO_PLUGIN_DIR, info->path, strerror(ENAMETOOLONG)); } } if (stat(path, &sb) != 0) error(1, "%s", path); if (sb.st_uid != ROOT_UID) errorx(1, "%s must be owned by uid %d", path, ROOT_UID); if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) errorx(1, "%s must be only be writable by owner", path); /* Open plugin and map in symbol */ handle = dlopen(path, RTLD_LAZY|RTLD_LOCAL); if (!handle) errorx(1, "unable to dlopen %s: %s", path, dlerror()); plugin = dlsym(handle, info->symbol_name); if (!plugin) errorx(1, "unable to find symbol %s in %s", info->symbol_name, path); if (plugin->type != SUDO_POLICY_PLUGIN && plugin->type != SUDO_IO_PLUGIN) { errorx(1, "%s: unknown policy type %d", path, plugin->type); } if (SUDO_API_VERSION_GET_MAJOR(plugin->version) != SUDO_API_VERSION_MAJOR) { errorx(1, "%s: incompatible policy major version %d, expected %d", path, SUDO_API_VERSION_GET_MAJOR(plugin->version), SUDO_API_VERSION_MAJOR); } if (plugin->type == SUDO_POLICY_PLUGIN) { if (policy_plugin->handle) errorx(1, "only a single policy plugin may be loaded"); policy_plugin->handle = handle; policy_plugin->name = info->symbol_name; policy_plugin->u.generic = plugin; } else if (plugin->type == SUDO_IO_PLUGIN) { container = emalloc(sizeof(*container)); container->prev = container; container->next = NULL; container->handle = handle; container->name = info->symbol_name; container->u.generic = plugin; tq_append(io_plugins, container); } } if (policy_plugin->handle == NULL) errorx(1, "%s: at least one policy plugin must be specified", conf_file); if (policy_plugin->u.policy->check_policy == NULL) errorx(1, "policy plugin %s does not include a check_policy method"); }