int main(int argc, char **argv) { clearenv(); init(); printf("Initial: "); print(); check_perms(); printf("* TEMPORARY DROP \n"); drop_temporarily(); check_perms(); printf("* RESTORE \n"); restore(); check_perms(); printf("* PERNAMENT DROP \n"); drop_pernamently(); check_perms(); printf("* RESTORE (we should fail now) \n"); restore(); check_perms(); return 0; }
static void alarm_handler(int sig) { axio_eolmode(NodeIo, EOLMODE_TEXT); axio_puts("\n",NodeIo); if (check_perms(PERM_ANSI, 0L) != -1) { axio_printf(NodeIo,"\e[05;31m"); }
/* * main - groupadd command */ int main (int argc, char **argv) { /* * Get my name so that I can use it to report errors. */ Prog = Basename (argv[0]); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); process_root_flag ("-R", argc, argv); prefix = process_prefix_flag ("-P", argc, argv); OPENLOG ("groupadd"); #ifdef WITH_AUDIT audit_help_open (); #endif if (atexit (do_cleanups) != 0) { fprintf (stderr, _("%s: Cannot setup cleanup service.\n"), Prog); exit (1); } /* * Parse the command line options. */ process_flags (argc, argv); check_perms (); #ifdef SHADOWGRP is_shadow_grp = sgr_file_present (); #endif /* * Do the hard stuff - open the files, create the group entries, * then close and update the files. */ open_files (); if (!gflg) { if (find_new_gid (rflg, &group_id, NULL) < 0) { exit (E_GID_IN_USE); } } grp_update (); close_files (); nscd_flush_cache ("group"); return E_SUCCESS; }
void handle_property_set_fd() { prop_msg msg; int s; int r; int res; struct ucred cr; struct sockaddr_un addr; socklen_t addr_size = sizeof(addr); socklen_t cr_size = sizeof(cr); if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) { return; } /* Check socket options here */ if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) { close(s); ERROR("Unable to recieve socket options\n"); return; } r = recv(s, &msg, sizeof(msg), 0); close(s); if(r != sizeof(prop_msg)) { ERROR("sys_prop: mis-match msg size recieved: %d expected: %d\n", r, sizeof(prop_msg)); return; } switch(msg.cmd) { case PROP_MSG_SETPROP: msg.name[PROP_NAME_MAX-1] = 0; msg.value[PROP_VALUE_MAX-1] = 0; if(memcmp(msg.name,"ctl.",4) == 0) { if (check_control_perms(msg.value, cr.uid, cr.gid)) { handle_control_message((char*) msg.name + 4, (char*) msg.value); } else { ERROR("sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n", msg.name + 4, msg.value, cr.uid, cr.pid); } } else { if (check_perms(msg.name, cr.uid, cr.gid)) { property_set((char*) msg.name, (char*) msg.value); } else { ERROR("sys_prop: permission denied uid:%d name:%s\n", cr.uid, msg.name); } } break; default: break; } }
void load_upsdconf(int reloading) { char fn[SMALLBUF]; PCONF_CTX_t ctx; snprintf(fn, sizeof(fn), "%s/upsd.conf", confpath()); check_perms(fn); pconf_init(&ctx, upsd_conf_err); if (!pconf_file_begin(&ctx, fn)) { pconf_finish(&ctx); if (!reloading) fatalx(EXIT_FAILURE, "%s", ctx.errmsg); upslogx(LOG_ERR, "Reload failed: %s", ctx.errmsg); return; } while (pconf_file_next(&ctx)) { if (pconf_parse_error(&ctx)) { upslogx(LOG_ERR, "Parse error: %s:%d: %s", fn, ctx.linenum, ctx.errmsg); continue; } if (ctx.numargs < 1) continue; if (!parse_upsd_conf_args(ctx.numargs, ctx.arglist)) { unsigned int i; char errmsg[SMALLBUF]; snprintf(errmsg, sizeof(errmsg), "upsd.conf: invalid directive"); for (i = 0; i < ctx.numargs; i++) snprintfcat(errmsg, sizeof(errmsg), " %s", ctx.arglist[i]); upslogx(LOG_WARNING, "%s", errmsg); } } pconf_finish(&ctx); }
int do_sendto(message *dev_m_in, message *dev_m_out) { int minor; int rc; struct sockaddr_un addr; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] do_sendto() call_count=%d\n", uds_minor(dev_m_in), ++call_count); #endif minor = uds_minor(dev_m_in); if (uds_fd_table[minor].type != SOCK_DGRAM) { /* This IOCTL is only for SOCK_DGRAM sockets */ return EINVAL; } rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un), D); if (rc != OK) { return EIO; } /* do some basic sanity checks on the address */ if (addr.sun_family != AF_UNIX || addr.sun_path[0] == '\0') { /* bad address */ return EINVAL; } rc = check_perms(minor, &addr); if (rc != OK) { return rc; } memcpy(&(uds_fd_table[minor].target), &addr, sizeof(struct sockaddr_un)); return OK; }
int do_links(int argc, char **argv) { struct ax_routes *axrt, *p; char digipath[AX25_MAX_DIGIS*10]; char tipoconn[9]; int i=0; axio_puts("",NodeIo); if (User.ul_type == AF_NETROM) { axio_printf(NodeIo,"%s} ", NodeId); } if ((axrt=read_ax_routes()) == NULL) { if (errno) node_perror("do_links: read_ax_routes", errno); else axio_printf(NodeIo,"No known links"); if (User.ul_type == AF_NETROM) { node_msg(""); } return 0; } /* "links" */ if (check_perms(PERM_ANSI, 0L) != -1) { axio_printf(NodeIo, "\e[01;33m"); }
/* * Initiate a AX.25, NET/ROM, ROSE or TCP connection to the host * specified by `address'. */ static ax25io *connect_to(char **addr, int family, int escape, int compr) { int fd; ax25io *riop; fd_set read_fdset; fd_set write_fdset; int salen; union { struct full_sockaddr_ax25 ax; #ifdef HAVE_ROSE struct sockaddr_rose rs; #endif struct sockaddr_in in; } sa; char call[10], path[20], *cp, *eol; int ret, retlen = sizeof(int); int paclen; struct hostent *hp; struct servent *sp; struct user u; #ifdef HAVE_NETROM struct proc_nr_nodes *np; #endif strcpy(call, User.call); /* * Fill in protocol spesific stuff. */ switch (family) { #ifdef HAVE_ROSE case AF_ROSE: if (aliascmd==0) { if (check_perms(PERM_ROSE, 0L) == -1) { axio_printf(NodeIo,"Permission denied"); if (User.ul_type == AF_NETROM) { node_msg(""); } node_log(LOGLVL_GW, "Permission denied: rose"); return NULL; } } if ((fd = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) { node_perror("connect_to: socket", errno); return NULL; } sa.rs.srose_family = AF_ROSE; sa.rs.srose_ndigis = 0; ax25_aton_entry(call, sa.rs.srose_call.ax25_call); rose_aton(rs_config_get_addr(NULL), sa.rs.srose_addr.rose_addr); salen = sizeof(struct sockaddr_rose); if (bind(fd, (struct sockaddr *)&sa, salen) == -1) { node_perror("connect_to: bind", errno); close(fd); return NULL; } memset(path, 0, 11); memcpy(path, rs_config_get_addr(NULL), 4); salen = strlen(addr[1]); if ((salen != 6) && (salen != 10)) { axio_printf(NodeIo,"Invalid ROSE address"); if (User.ul_type == AF_NETROM) { node_msg(""); } return(NULL); } memcpy(path + (10-salen), addr[1], salen); sprintf(User.dl_name, "%s @ %s", addr[0], path); sa.rs.srose_family = AF_ROSE; sa.rs.srose_ndigis = 0; if (ax25_aton_entry(addr[0], sa.rs.srose_call.ax25_call) < 0) { close(fd); return NULL; } if (rose_aton(path, sa.rs.srose_addr.rose_addr) < 0) { close(fd); return NULL; } if (addr[2] != NULL) { if (ax25_aton_entry(addr[2], sa.rs.srose_digi.ax25_call) < 0) { close(fd); return NULL; } sa.rs.srose_ndigis = 1; } salen = sizeof(struct sockaddr_rose); paclen = rs_config_get_paclen(NULL); eol = ROSE_EOL; /* Uncomment the below if you wish to have the node show a 'Trying' state */ /* node_msg("%s Trying %s... Type <RETURN> to abort", User.dl_name); */ break; #endif #ifdef HAVE_NETROM case AF_NETROM: if (aliascmd==0) { if (check_perms(PERM_NETROM, 0L) == -1) { axio_printf(NodeIo,"Permission denied"); if (User.ul_type == AF_NETROM) { node_msg(""); } node_log(LOGLVL_GW, "Permission denied: netrom"); return NULL; } } if ((fd = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) { node_perror("connect_to: socket", errno); return NULL; } /* Why on earth is this different from ax.25 ????? */ sprintf(path, "%s %s", nr_config_get_addr(NrPort), call); ax25_aton(path, &sa.ax); sa.ax.fsa_ax25.sax25_family = AF_NETROM; salen = sizeof(struct full_sockaddr_ax25); if (bind(fd, (struct sockaddr *)&sa, salen) == -1) { node_perror("connect_to: bind", errno); close(fd); return NULL; } if ((np = find_node(addr[0], NULL)) == NULL) { axio_printf(NodeIo,"No such node"); if (User.ul_type == AF_NETROM) { node_msg(""); } return NULL; } strcpy(User.dl_name, print_node(np->alias, np->call)); if (ax25_aton(np->call, &sa.ax) == -1) { close(fd); return NULL; } sa.ax.fsa_ax25.sax25_family = AF_NETROM; salen = sizeof(struct sockaddr_ax25); paclen = nr_config_get_paclen(NrPort); eol = NETROM_EOL; /* Uncomment the below if you wish the node to show a 'Trying' state */ if (check_perms(PERM_ANSI, 0L) != -1) { if (User.ul_type == AF_NETROM) { break; } node_msg("\e[01;36mTrying %s... hit <Enter> to abort", User.dl_name); } break; #endif #ifdef HAVE_AX25 case AF_FLEXNET: case AF_AX25: if (aliascmd==0) { if (check_perms(PERM_AX25, 0L) == -1 || (is_hidden(addr[0]) && check_perms(PERM_HIDDEN, 0L) == -1)) { axio_printf(NodeIo,"Permission denied"); if (User.ul_type == AF_NETROM) { node_msg(""); } node_log(LOGLVL_GW, "Permission denied: ax.25 port %s", addr[0]); return NULL; } } if (ax25_config_get_addr(addr[0]) == NULL) { if (User.ul_type == AF_NETROM) { axio_printf(NodeIo,"%s} ", NodeId); } axio_printf(NodeIo,"Invalid port"); if (User.ul_type == AF_NETROM) { node_msg(""); } return NULL; } if ((fd = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) { node_perror("connect_to: socket", errno); return NULL; } /* * Invert the SSID only if user is coming in with AX.25 * and going out on the same port he is coming in via. */ if (User.ul_type == AF_AX25 && !strcasecmp(addr[0], User.ul_name)) invert_ssid(call, User.call); sprintf(path, "%s %s", call, ax25_config_get_addr(addr[0])); ax25_aton(path, &sa.ax); sa.ax.fsa_ax25.sax25_family = AF_AX25; salen = sizeof(struct full_sockaddr_ax25); if (bind(fd, (struct sockaddr *)&sa, salen) < 0) { node_perror("connect_to: bind", errno); close(fd); return NULL; } if (ax25_aton_arglist((const char **)addr+1, &sa.ax) < 0) { close(fd); return NULL; } strcpy(User.dl_name, strupr(addr[1])); strcpy(User.dl_port, strlwr(addr[0])); sa.ax.fsa_ax25.sax25_family = AF_AX25; salen = sizeof(struct full_sockaddr_ax25); paclen = ax25_config_get_paclen(addr[0]); eol = AX25_EOL; /* Uncomment the below if you wish the node to show a 'Trying' state */ /* if (family==AF_FLEXNET) node_msg("Trying %s via FlexNet... Type <RETURN> to abort", User.dl_name); */ if ((family==AF_FLEXNET) || (family == AF_AX25)) { if (!strcmp(User.dl_port,User.ul_name)) { if (check_perms(PERM_ANSI, 0L) != -1) { axio_printf(NodeIo, "\e[05;31m"); } axio_printf(NodeIo,"\aLoop detected on "); } if (check_perms(PERM_ANSI, 0L) != -1) { axio_printf(NodeIo, "\e[0;m"); } if (User.ul_type == AF_NETROM) { axio_printf(NodeIo, "%s} ", NodeId); } if (check_perms(PERM_ANSI, 0L) != -1) { axio_printf(NodeIo, "\e[01;33m"); }
/* * gpasswd - administer the /etc/group file */ int main (int argc, char **argv) { struct group grent; #ifdef SHADOWGRP struct sgrp sgent; #endif struct passwd *pw = NULL; #ifdef WITH_AUDIT audit_help_open (); #endif sanitize_env (); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); /* * Make a note of whether or not this command was invoked by root. * This will be used to bypass certain checks later on. Also, set * the real user ID to match the effective user ID. This will * prevent the invoker from issuing signals which would interfere * with this command. */ bywho = getuid (); Prog = Basename (argv[0]); OPENLOG ("gpasswd"); setbuf (stdout, NULL); setbuf (stderr, NULL); #ifdef SHADOWGRP is_shadowgrp = sgr_file_present (); #endif /* * Determine the name of the user that invoked this command. This * is really hit or miss because there are so many ways that command * can be executed and so many ways to trip up the routines that * report the user name. */ pw = get_my_pwent (); if (NULL == pw) { fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", (unsigned long) getuid ())); exit (E_NOPERM); } myname = xstrdup (pw->pw_name); /* * Register an exit function to warn for any inconsistency that we * could create. */ if (atexit (do_cleanups) != 0) { fprintf(stderr, "%s: cannot set exit function\n", Prog); exit (1); } /* Parse the options */ process_flags (argc, argv); /* * Replicate the group so it can be modified later on. */ #ifdef SHADOWGRP get_group (&grent, &sgent); #else get_group (&grent); #endif /* * Check if the user is allowed to change the password of this group. */ #ifdef SHADOWGRP check_perms (&grent, &sgent); #else check_perms (&grent); #endif /* * Removing a password is straight forward. Just set the password * field to a "". */ if (rflg) { grent.gr_passwd = ""; /* XXX warning: const */ #ifdef SHADOWGRP sgent.sg_passwd = ""; /* XXX warning: const */ #endif goto output; } else if (Rflg) { /* * Same thing for restricting the group. Set the password * field to "!". */ grent.gr_passwd = "!"; /* XXX warning: const */ #ifdef SHADOWGRP sgent.sg_passwd = "!"; /* XXX warning: const */ #endif goto output; } /* * Adding a member to a member list is pretty straightforward as * well. Call the appropriate routine and split. */ if (aflg) { printf (_("Adding user %s to group %s\n"), user, group); grent.gr_mem = add_list (grent.gr_mem, user); #ifdef SHADOWGRP if (is_shadowgrp) { sgent.sg_mem = add_list (sgent.sg_mem, user); } #endif goto output; } /* * Removing a member from the member list is the same deal as adding * one, except the routine is different. */ if (dflg) { bool removed = false; printf (_("Removing user %s from group %s\n"), user, group); if (is_on_list (grent.gr_mem, user)) { removed = true; grent.gr_mem = del_list (grent.gr_mem, user); } #ifdef SHADOWGRP if (is_shadowgrp) { if (is_on_list (sgent.sg_mem, user)) { removed = true; sgent.sg_mem = del_list (sgent.sg_mem, user); } } #endif if (!removed) { fprintf (stderr, _("%s: user '%s' is not a member of '%s'\n"), Prog, user, group); exit (E_BAD_ARG); } goto output; } #ifdef SHADOWGRP /* * Replacing the entire list of administrators is simple. Check the * list to make sure everyone is a real user. Then slap the new list * in place. */ if (Aflg) { sgent.sg_adm = comma_to_list (admins); if (!Mflg) { goto output; } } #endif /* SHADOWGRP */ /* * Replacing the entire list of members is simple. Check the list to * make sure everyone is a real user. Then slap the new list in * place. */ if (Mflg) { #ifdef SHADOWGRP sgent.sg_mem = comma_to_list (members); #endif grent.gr_mem = comma_to_list (members); goto output; } /* * If the password is being changed, the input and output must both * be a tty. The typical keyboard signals are caught so the termio * modes can be restored. */ if ((isatty (0) == 0) || (isatty (1) == 0)) { fprintf (stderr, _("%s: Not a tty\n"), Prog); exit (E_NOPERM); } catch_signals (0); /* save tty modes */ (void) signal (SIGHUP, catch_signals); (void) signal (SIGINT, catch_signals); (void) signal (SIGQUIT, catch_signals); (void) signal (SIGTERM, catch_signals); #ifdef SIGTSTP (void) signal (SIGTSTP, catch_signals); #endif /* Prompt for the new password */ #ifdef SHADOWGRP change_passwd (&grent, &sgent); #else change_passwd (&grent); #endif /* * This is the common arrival point to output the new group file. * The freshly crafted entry is in allocated space. The group file * will be locked and opened for writing. The new entry will be * output, etc. */ output: if (setuid (0) != 0) { fputs (_("Cannot change ID to root.\n"), stderr); SYSLOG ((LOG_ERR, "can't setuid(0)")); closelog (); exit (E_NOPERM); } pwd_init (); open_files (); #ifdef SHADOWGRP update_group (&grent, &sgent); #else update_group (&grent); #endif close_files (); nscd_flush_cache ("group"); exit (E_SUCCESS); }
/* * chfn - change a user's password file information * * This command controls the GECOS field information in the password * file entry. * * The valid options are * * -f full name * -r room number * -w work phone number * -h home phone number * -o other information (*) * * (*) requires root permission to execute. */ int main (int argc, char **argv) { const struct passwd *pw; /* password file entry */ char new_gecos[BUFSIZ]; /* buffer for new GECOS fields */ char *user; /* * Get the program name. The program name is used as a * prefix to most error messages. */ Prog = Basename (argv[0]); sanitize_env (); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); process_root_flag ("-R", argc, argv); /* * This command behaves different for root and non-root * users. */ amroot = (getuid () == 0); OPENLOG ("chfn"); /* parse the command line options */ process_flags (argc, argv); /* * Get the name of the user to check. It is either the command line * name, or the name getlogin() returns. */ if (optind < argc) { user = argv[optind]; pw = xgetpwnam (user); if (NULL == pw) { fprintf (stderr, _("%s: user '%s' does not exist\n"), Prog, user); fail_exit (E_NOPERM); } } else { pw = get_my_pwent (); if (NULL == pw) { fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", (unsigned long) getuid ())); fail_exit (E_NOPERM); } user = xstrdup (pw->pw_name); } #ifdef USE_NIS /* * Now we make sure this is a LOCAL password entry for this user ... */ if (__ispwNIS ()) { char *nis_domain; char *nis_master; fprintf (stderr, _("%s: cannot change user '%s' on NIS client.\n"), Prog, user); if (!yp_get_default_domain (&nis_domain) && !yp_master (nis_domain, "passwd.byname", &nis_master)) { fprintf (stderr, _ ("%s: '%s' is the NIS master for this client.\n"), Prog, nis_master); } fail_exit (E_NOPERM); } #endif /* Check that the caller is allowed to change the gecos of the * specified user */ check_perms (pw); /* If some fields were not set on the command line, load the value from * the old gecos fields. */ get_old_fields (pw->pw_gecos); /* * If none of the fields were changed from the command line, let the * user interactively change them. */ if (!fflg && !rflg && !wflg && !hflg && !oflg) { printf (_("Changing the user information for %s\n"), user); new_fields (); } /* * Check all of the fields for valid information */ check_fields (); /* * Build the new GECOS field by plastering all the pieces together, * if they will fit ... */ if ((strlen (fullnm) + strlen (roomno) + strlen (workph) + strlen (homeph) + strlen (slop)) > (unsigned int) 80) { fprintf (stderr, _("%s: fields too long\n"), Prog); fail_exit (E_NOPERM); } snprintf (new_gecos, sizeof new_gecos, "%s,%s,%s,%s%s%s", fullnm, roomno, workph, homeph, ('\0' != slop[0]) ? "," : "", slop); /* Rewrite the user's gecos in the passwd file */ update_gecos (user, new_gecos); SYSLOG ((LOG_INFO, "changed user '%s' information", user)); nscd_flush_cache ("passwd"); closelog (); exit (E_SUCCESS); }
int do_bind(message *dev_m_in, message *dev_m_out) { int minor; struct sockaddr_un addr; int rc, i; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] do_bind() call_count=%d\n", uds_minor(dev_m_in), ++call_count); #endif minor = uds_minor(dev_m_in); if ((uds_fd_table[minor].type == -1) || (uds_fd_table[minor].addr.sun_family == AF_UNIX && uds_fd_table[minor].type != SOCK_DGRAM)) { /* the type hasn't been set by do_socket() yet OR attempting * to re-bind() a non-SOCK_DGRAM socket */ return EINVAL; } rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un)); if (rc != OK) { return EIO; } /* do some basic sanity checks on the address */ if (addr.sun_family != AF_UNIX) { /* bad family */ return EAFNOSUPPORT; } if (addr.sun_path[0] == '\0') { /* bad address */ return ENOENT; } rc = check_perms(minor, &addr); if (rc != OK) { /* permission denied, socket file doesn't exist, etc. */ return rc; } /* make sure the address isn't already in use by another socket. */ for (i = 0; i < NR_FDS; i++) { if ((uds_fd_table[i].addr.sun_family == AF_UNIX) && !strncmp(addr.sun_path, uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) { /* another socket is bound to this sun_path */ return EADDRINUSE; } } /* looks good, perform the bind() */ memcpy(&(uds_fd_table[minor].addr), &addr, sizeof(struct sockaddr_un)); return OK; }
void handle_property_set_fd() { prop_msg msg; int s; int r; int res; struct ucred cr; struct sockaddr_un addr; socklen_t addr_size = sizeof(addr); socklen_t cr_size = sizeof(cr); char * source_ctx = NULL; struct pollfd ufds[1]; const int timeout_ms = 2 * 1000; /* Default 2 sec timeout for caller to send property. */ int nr; if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) { return; } /* Check socket options here */ if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) { close(s); ERROR("Unable to receive socket options\n"); return; } ufds[0].fd = s; ufds[0].events = POLLIN; ufds[0].revents = 0; nr = TEMP_FAILURE_RETRY(poll(ufds, 1, timeout_ms)); if (nr == 0) { ERROR("sys_prop: timeout waiting for pid=%d uid=%d gid=%d to send property message.\n", cr.pid, cr.uid, cr.gid); close(s); return; } else if (nr < 0) { ERROR("sys_prop: error waiting for pid=%d uid=%d gid=%d to send property message. err=%d %s\n", cr.pid, cr.uid, cr.gid, errno, strerror(errno)); close(s); return; } r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), MSG_DONTWAIT)); if(r != sizeof(prop_msg)) { ERROR("sys_prop: mis-match msg size received: %d from pid=%d uid=%d gid=%d expected: %zu errno: %d\n", r, cr.pid, cr.uid, cr.gid, sizeof(prop_msg), errno); close(s); return; } switch(msg.cmd) { case PROP_MSG_SETPROP: msg.name[PROP_NAME_MAX-1] = 0; msg.value[PROP_VALUE_MAX-1] = 0; if (!is_legal_property_name(msg.name, strlen(msg.name))) { ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name); close(s); return; } getpeercon(s, &source_ctx); if(memcmp(msg.name,"ctl.",4) == 0) { // Keep the old close-socket-early behavior when handling // ctl.* properties. close(s); if (check_control_mac_perms(msg.value, source_ctx)) { #ifdef MTK_INIT INFO("[PropSet]: pid:%u uid:%u gid:%u %s %s\n", cr.pid, cr.uid, cr.gid, msg.name, msg.value); #endif handle_control_message((char*) msg.name + 4, (char*) msg.value); } else { ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n", msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid); } } else { if (check_perms(msg.name, source_ctx)) { #ifdef MTK_INIT INFO("[PropSet]: pid:%u uid:%u gid:%u set %s=%s\n", cr.pid, cr.uid, cr.gid, msg.name, msg.value); if(strcmp(msg.name, ANDROID_RB_PROPERTY) == 0) { INFO("pid %d set %s=%s\n", cr.pid, msg.name, msg.value); reboot_pid(cr.pid); } #endif property_set((char*) msg.name, (char*) msg.value); } else { ERROR("sys_prop: permission denied uid:%d name:%s\n", cr.uid, msg.name); } // Note: bionic's property client code assumes that the // property server will not close the socket until *AFTER* // the property is written to memory. close(s); } freecon(source_ctx); break; default: close(s); break; } }
int main (int argc, char **argv) { char buf[BUFSIZ]; char *name; char *newpwd; char *cp; #ifndef USE_PAM const struct spwd *sp; struct spwd newsp; const struct passwd *pw; struct passwd newpw; #endif /* !USE_PAM */ int errors = 0; int line = 0; Prog = Basename (argv[0]); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); process_flags (argc, argv); OPENLOG ("chpasswd"); check_perms (); #ifndef USE_PAM is_shadow_pwd = spw_file_present (); open_files (); #endif /* * Read each line, separating the user name from the password. The * password entry for each user will be looked up in the appropriate * file (shadow or passwd) and the password changed. For shadow * files the last change date is set directly, for passwd files the * last change date is set in the age only if aging information is * present. */ while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) { line++; cp = strrchr (buf, '\n'); if (NULL != cp) { *cp = '\0'; } else { if (feof (stdin) == 0) { fprintf (stderr, _("%s: line %d: line too long\n"), Prog, line); errors++; continue; } } /* * The username is the first field. It is separated from the * password with a ":" character which is replaced with a * NUL to give the new password. The new password will then * be encrypted in the normal fashion with a new salt * generated, unless the '-e' is given, in which case it is * assumed to already be encrypted. */ name = buf; cp = strchr (name, ':'); if (NULL != cp) { *cp = '\0'; cp++; } else { fprintf (stderr, _("%s: line %d: missing new password\n"), Prog, line); errors++; continue; } newpwd = cp; #ifdef USE_PAM if (do_pam_passwd_non_interractive ("chpasswd", name, newpwd) != 0) { fprintf (stderr, _("%s: (line %d, user %s) password not changed\n"), Prog, line, name); errors++; } #else /* !USE_PAM */ if ( !eflg && ( (NULL == crypt_method) || (0 != strcmp (crypt_method, "NONE")))) { void *arg = NULL; if (md5flg) { crypt_method = "MD5"; } else if (crypt_method != NULL) { #ifdef USE_SHA_CRYPT if (sflg) { arg = &sha_rounds; } #endif } else { crypt_method = NULL; } cp = pw_encrypt (newpwd, crypt_make_salt(crypt_method, arg)); } /* * Get the password file entry for this user. The user must * already exist. */ pw = pw_locate (name); if (NULL == pw) { fprintf (stderr, _("%s: line %d: user '%s' does not exist\n"), Prog, line, name); errors++; continue; } if (is_shadow_pwd) { sp = spw_locate (name); } else { sp = NULL; } /* * The freshly encrypted new password is merged into the * user's password file entry and the last password change * date is set to the current date. */ if (NULL != sp) { newsp = *sp; newsp.sp_pwdp = cp; newsp.sp_lstchg = (long) time ((time_t *)NULL) / SCALE; if (0 == newsp.sp_lstchg) { /* Better disable aging than requiring a * password change */ newsp.sp_lstchg = -1; } } else { newpw = *pw; newpw.pw_passwd = cp; } /* * The updated password file entry is then put back and will * be written to the password file later, after all the * other entries have been updated as well. */ if (NULL != sp) { if (spw_update (&newsp) == 0) { fprintf (stderr, _("%s: line %d: failed to prepare the new %s entry '%s'\n"), Prog, line, spw_dbname (), newsp.sp_namp); errors++; continue; } } else { if (pw_update (&newpw) == 0) { fprintf (stderr, _("%s: line %d: failed to prepare the new %s entry '%s'\n"), Prog, line, pw_dbname (), newpw.pw_name); errors++; continue; } } #endif /* !USE_PAM */ } /* * Any detected errors will cause the entire set of changes to be * aborted. Unlocking the password file will cause all of the * changes to be ignored. Otherwise the file is closed, causing the * changes to be written out all at once, and then unlocked * afterwards. * * With PAM, it is not possible to delay the update of the * password database. */ if (0 != errors) { #ifndef USE_PAM fprintf (stderr, _("%s: error detected, changes ignored\n"), Prog); #endif fail_exit (1); } #ifndef USE_PAM /* Save the changes */ close_files (); #endif nscd_flush_cache ("passwd"); return (0); }
int main (int argc, char **argv) { char buf[BUFSIZ]; char *fields[8]; int nfields; char *cp; const struct passwd *pw; struct passwd newpw; int errors = 0; int line = 0; uid_t uid; gid_t gid; #ifdef USE_PAM int *lines = NULL; char **usernames = NULL; char **passwords = NULL; unsigned int nusers = 0; #endif /* USE_PAM */ Prog = Basename (argv[0]); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); /* FIXME: will not work with an input file */ process_root_flag ("-R", argc, argv); OPENLOG ("newusers"); process_flags (argc, argv); check_perms (); is_shadow = spw_file_present (); #ifdef SHADOWGRP is_shadow_grp = sgr_file_present (); #endif #ifdef ENABLE_SUBIDS is_sub_uid = sub_uid_file_present () && !rflg; is_sub_gid = sub_gid_file_present () && !rflg; #endif /* ENABLE_SUBIDS */ open_files (); /* * Read each line. The line has the same format as a password file * entry, except that certain fields are not constrained to be * numerical values. If a group ID is entered which does not already * exist, an attempt is made to allocate the same group ID as the * numerical user ID. Should that fail, the next available group ID * over 100 is allocated. The pw_gid field will be updated with that * value. */ while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) { line++; cp = strrchr (buf, '\n'); if (NULL != cp) { *cp = '\0'; } else { if (feof (stdin) == 0) { fprintf (stderr, _("%s: line %d: line too long\n"), Prog, line); errors++; continue; } } /* * Break the string into fields and screw around with them. * There MUST be 7 colon separated fields, although the * values aren't that particular. */ for (cp = buf, nfields = 0; nfields < 7; nfields++) { fields[nfields] = cp; cp = strchr (cp, ':'); if (NULL != cp) { *cp = '\0'; cp++; } else { break; } } if (nfields != 6) { fprintf (stderr, _("%s: line %d: invalid line\n"), Prog, line); errors++; continue; } /* * First check if we have to create or update an user */ pw = pw_locate (fields[0]); /* local, no need for xgetpwnam */ if ( (NULL == pw) && (getpwnam (fields[0]) != NULL)) { fprintf (stderr, _("%s: cannot update the entry of user %s (not in the passwd database)\n"), Prog, fields[0]); errors++; continue; } if ( (NULL == pw) && (get_user_id (fields[2], &uid) != 0)) { fprintf (stderr, _("%s: line %d: can't create user\n"), Prog, line); errors++; continue; } /* * Processed is the group name. A new group will be * created if the group name is non-numeric and does not * already exist. If the group name is a number (which is not * an existing GID), a group with the same name as the user * will be created, with the given GID. The given or created * group will be the primary group of the user. If * there is no named group to be a member of, the UID will * be figured out and that value will be a candidate for a * new group, if that group ID exists, a whole new group ID * will be made up. */ if ( (NULL == pw) && (add_group (fields[0], fields[3], &gid, uid) != 0)) { fprintf (stderr, _("%s: line %d: can't create group\n"), Prog, line); errors++; continue; } /* * Now we work on the user ID. It has to be specified either * as a numerical value, or left blank. If it is a numerical * value, that value will be used, otherwise the next * available user ID is computed and used. After this there * will at least be a (struct passwd) for the user. */ if ( (NULL == pw) && (add_user (fields[0], uid, gid) != 0)) { fprintf (stderr, _("%s: line %d: can't create user\n"), Prog, line); errors++; continue; } /* * The password, gecos field, directory, and shell fields * all come next. */ pw = pw_locate (fields[0]); if (NULL == pw) { fprintf (stderr, _("%s: line %d: user '%s' does not exist in %s\n"), Prog, line, fields[0], pw_dbname ()); errors++; continue; } newpw = *pw; #ifdef USE_PAM /* keep the list of user/password for later update by PAM */ nusers++; lines = realloc (lines, sizeof (lines[0]) * nusers); usernames = realloc (usernames, sizeof (usernames[0]) * nusers); passwords = realloc (passwords, sizeof (passwords[0]) * nusers); lines[nusers-1] = line; usernames[nusers-1] = strdup (fields[0]); passwords[nusers-1] = strdup (fields[1]); #endif /* USE_PAM */ if (add_passwd (&newpw, fields[1]) != 0) { fprintf (stderr, _("%s: line %d: can't update password\n"), Prog, line); errors++; continue; } if ('\0' != fields[4][0]) { newpw.pw_gecos = fields[4]; } if ('\0' != fields[5][0]) { newpw.pw_dir = fields[5]; } if ('\0' != fields[6][0]) { newpw.pw_shell = fields[6]; } if ( ('\0' != fields[5][0]) && (access (newpw.pw_dir, F_OK) != 0)) { /* FIXME: should check for directory */ mode_t msk = 0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK); if (mkdir (newpw.pw_dir, msk) != 0) { fprintf (stderr, _("%s: line %d: mkdir %s failed: %s\n"), Prog, line, newpw.pw_dir, strerror (errno)); } else if (chown (newpw.pw_dir, newpw.pw_uid, newpw.pw_gid) != 0) { fprintf (stderr, _("%s: line %d: chown %s failed: %s\n"), Prog, line, newpw.pw_dir, strerror (errno)); } } /* * Update the password entry with the new changes made. */ if (pw_update (&newpw) == 0) { fprintf (stderr, _("%s: line %d: can't update entry\n"), Prog, line); errors++; continue; } #ifdef ENABLE_SUBIDS /* * Add subordinate uids if the user does not have them. */ if (is_sub_uid && !sub_uid_assigned(fields[0])) { uid_t sub_uid_start = 0; unsigned long sub_uid_count = 0; if (find_new_sub_uids(fields[0], &sub_uid_start, &sub_uid_count) == 0) { if (sub_uid_add(fields[0], sub_uid_start, sub_uid_count) == 0) { fprintf (stderr, _("%s: failed to prepare new %s entry\n"), Prog, sub_uid_dbname ()); } } else { fprintf (stderr, _("%s: can't find subordinate user range\n"), Prog); errors++; } } /* * Add subordinate gids if the user does not have them. */ if (is_sub_gid && !sub_gid_assigned(fields[0])) { gid_t sub_gid_start = 0; unsigned long sub_gid_count = 0; if (find_new_sub_gids(fields[0], &sub_gid_start, &sub_gid_count) == 0) { if (sub_gid_add(fields[0], sub_gid_start, sub_gid_count) == 0) { fprintf (stderr, _("%s: failed to prepare new %s entry\n"), Prog, sub_uid_dbname ()); } } else { fprintf (stderr, _("%s: can't find subordinate group range\n"), Prog); errors++; } } #endif /* ENABLE_SUBIDS */ } /* * Any detected errors will cause the entire set of changes to be * aborted. Unlocking the password file will cause all of the * changes to be ignored. Otherwise the file is closed, causing the * changes to be written out all at once, and then unlocked * afterwards. */ if (0 != errors) { fprintf (stderr, _("%s: error detected, changes ignored\n"), Prog); fail_exit (EXIT_FAILURE); } close_files (); nscd_flush_cache ("passwd"); nscd_flush_cache ("group"); sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); #ifdef USE_PAM unsigned int i; /* Now update the passwords using PAM */ for (i = 0; i < nusers; i++) { if (do_pam_passwd_non_interactive ("newusers", usernames[i], passwords[i]) != 0) { fprintf (stderr, _("%s: (line %d, user %s) password not changed\n"), Prog, lines[i], usernames[i]); errors++; } } #endif /* USE_PAM */ return ((0 == errors) ? EXIT_SUCCESS : EXIT_FAILURE); }
int main (int argc, char **argv) { const struct spwd *sp; uid_t ruid; gid_t rgid; const struct passwd *pw; /* * Get the program name so that error messages can use it. */ Prog = Basename (argv[0]); sanitize_env (); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); process_root_flag ("-R", argc, argv); #ifdef WITH_AUDIT audit_help_open (); #endif OPENLOG ("chage"); ruid = getuid (); rgid = getgid (); amroot = (ruid == 0); #ifdef WITH_SELINUX if (amroot && (is_selinux_enabled () > 0)) { amroot = (selinux_check_passwd_access (PASSWD__ROOTOK) == 0); } #endif process_flags (argc, argv); check_perms (); if (!spw_file_present ()) { fprintf (stderr, _("%s: the shadow password file is not present\n"), Prog); SYSLOG ((LOG_WARN, "can't find the shadow password file")); closelog (); exit (E_SHADOW_NOTFOUND); } open_files (lflg); /* Drop privileges */ if (lflg && ( (setregid (rgid, rgid) != 0) || (setreuid (ruid, ruid) != 0))) { fprintf (stderr, _("%s: failed to drop privileges (%s)\n"), Prog, strerror (errno)); fail_exit (E_NOPERM); } pw = pw_locate (argv[optind]); if (NULL == pw) { fprintf (stderr, _("%s: user '%s' does not exist in %s\n"), Prog, argv[optind], pw_dbname ()); closelog (); fail_exit (E_NOPERM); } STRFCPY (user_name, pw->pw_name); #ifdef WITH_TCB if (shadowtcb_set_user (pw->pw_name) == SHADOWTCB_FAILURE) { fail_exit (E_NOPERM); } #endif user_uid = pw->pw_uid; sp = spw_locate (argv[optind]); get_defaults (sp); /* * Print out the expiration fields if the user has requested the * list option. */ if (lflg) { if (!amroot && (ruid != user_uid)) { fprintf (stderr, _("%s: Permission denied.\n"), Prog); fail_exit (E_NOPERM); } #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "display aging info", user_name, (unsigned int) user_uid, 1); #endif list_fields (); fail_exit (E_SUCCESS); } /* * If none of the fields were changed from the command line, let the * user interactively change them. */ if (!mflg && !Mflg && !dflg && !Wflg && !Iflg && !Eflg) { printf (_("Changing the aging information for %s\n"), user_name); if (new_fields () == 0) { fprintf (stderr, _("%s: error changing fields\n"), Prog); fail_exit (E_NOPERM); } #ifdef WITH_AUDIT else { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change all aging information", user_name, (unsigned int) user_uid, 1); } #endif } else { #ifdef WITH_AUDIT if (Mflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change max age", user_name, (unsigned int) user_uid, 1); } if (mflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change min age", user_name, (unsigned int) user_uid, 1); } if (dflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change last change date", user_name, (unsigned int) user_uid, 1); } if (Wflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change passwd warning", user_name, (unsigned int) user_uid, 1); } if (Iflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change inactive days", user_name, (unsigned int) user_uid, 1); } if (Eflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change passwd expiration", user_name, (unsigned int) user_uid, 1); } #endif } update_age (sp, pw); close_files (); SYSLOG ((LOG_INFO, "changed password expiry for %s", user_name)); closelog (); exit (E_SUCCESS); }
int main (int argc, char **argv) { char buf[BUFSIZ]; char *name; char *newpwd; char *cp; #ifdef SHADOWGRP const struct sgrp *sg; struct sgrp newsg; #endif const struct group *gr; struct group newgr; int errors = 0; int line = 0; Prog = Basename (argv[0]); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); process_root_flag ("-R", argc, argv); process_flags (argc, argv); OPENLOG ("chgpasswd"); check_perms (); #ifdef SHADOWGRP is_shadow_grp = sgr_file_present (); #endif open_files (); /* * Read each line, separating the group name from the password. The * group entry for each group will be looked up in the appropriate * file (gshadow or group) and the password changed. */ while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) { line++; cp = strrchr (buf, '\n'); if (NULL != cp) { *cp = '\0'; } else { fprintf (stderr, _("%s: line %d: line too long\n"), Prog, line); errors++; continue; } /* * The group's name is the first field. It is separated from * the password with a ":" character which is replaced with a * NUL to give the new password. The new password will then * be encrypted in the normal fashion with a new salt * generated, unless the '-e' is given, in which case it is * assumed to already be encrypted. */ name = buf; cp = strchr (name, ':'); if (NULL != cp) { *cp = '\0'; cp++; } else { fprintf (stderr, _("%s: line %d: missing new password\n"), Prog, line); errors++; continue; } newpwd = cp; if ( (!eflg) && ( (NULL == crypt_method) || (0 != strcmp (crypt_method, "NONE")))) { void *arg = NULL; const char *salt; if (md5flg) { crypt_method = "MD5"; } #ifdef USE_SHA_CRYPT if (sflg) { arg = &sha_rounds; } #endif salt = crypt_make_salt (crypt_method, arg); cp = pw_encrypt (newpwd, salt); if (NULL == cp) { fprintf (stderr, _("%s: failed to crypt password with salt '%s': %s\n"), Prog, salt, strerror (errno)); fail_exit (1); } } /* * Get the group file entry for this group. The group must * already exist. */ gr = gr_locate (name); if (NULL == gr) { fprintf (stderr, _("%s: line %d: group '%s' does not exist\n"), Prog, line, name); errors++; continue; } #ifdef SHADOWGRP if (is_shadow_grp) { /* The gshadow entry should be updated if the * group entry has a password set to 'x'. * But on the other hand, if there is already both * a group and a gshadow password, it's preferable * to update both. */ sg = sgr_locate (name); if ( (NULL == sg) && (strcmp (gr->gr_passwd, SHADOW_PASSWD_STRING) == 0)) { static char *empty = NULL; /* If the password is set to 'x' in * group, but there are no entries in * gshadow, create one. */ newsg.sg_name = name; /* newsg.sg_passwd = NULL; will be set later */ newsg.sg_adm = ∅ newsg.sg_mem = dup_list (gr->gr_mem); sg = &newsg; } } else { sg = NULL; } #endif /* * The freshly encrypted new password is merged into the * group's entry. */ #ifdef SHADOWGRP if (NULL != sg) { newsg = *sg; newsg.sg_passwd = cp; } if ( (NULL == sg) || (strcmp (gr->gr_passwd, SHADOW_PASSWD_STRING) != 0)) #endif { newgr = *gr; newgr.gr_passwd = cp; } /* * The updated group file entry is then put back and will * be written to the group file later, after all the * other entries have been updated as well. */ #ifdef SHADOWGRP if (NULL != sg) { if (sgr_update (&newsg) == 0) { fprintf (stderr, _("%s: line %d: failed to prepare the new %s entry '%s'\n"), Prog, line, sgr_dbname (), newsg.sg_name); errors++; continue; } } if ( (NULL == sg) || (strcmp (gr->gr_passwd, SHADOW_PASSWD_STRING) != 0)) #endif { if (gr_update (&newgr) == 0) { fprintf (stderr, _("%s: line %d: failed to prepare the new %s entry '%s'\n"), Prog, line, gr_dbname (), newgr.gr_name); errors++; continue; } } } /* * Any detected errors will cause the entire set of changes to be * aborted. Unlocking the group file will cause all of the * changes to be ignored. Otherwise the file is closed, causing the * changes to be written out all at once, and then unlocked * afterwards. */ if (0 != errors) { fprintf (stderr, _("%s: error detected, changes ignored\n"), Prog); fail_exit (1); } close_files (); nscd_flush_cache ("group"); return (0); }
int do_connect(message *dev_m_in, message *dev_m_out) { int minor, child; struct sockaddr_un addr; int rc, i, j; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] do_connect() call_count=%d\n", uds_minor(dev_m_in), ++call_count); #endif minor = uds_minor(dev_m_in); /* only connection oriented sockets can connect */ if (uds_fd_table[minor].type != SOCK_STREAM && uds_fd_table[minor].type != SOCK_SEQPACKET) { return EINVAL; } if (uds_fd_table[minor].peer != -1) { /* socket is already connected */ return EISCONN; } rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un)); if (rc != OK) { return EIO; } rc = check_perms(minor, &addr); if (rc != OK) { /* permission denied, socket file doesn't exist, etc. */ return rc; } /* look for a socket of the same type that is listening on the * address we want to connect to */ for (i = 0; i < NR_FDS; i++) { if (uds_fd_table[minor].type == uds_fd_table[i].type && uds_fd_table[i].listening && uds_fd_table[i].addr.sun_family == AF_UNIX && !strncmp(addr.sun_path, uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) { if ((child = uds_fd_table[i].child) != -1) { /* the server is blocked on accept(2) -- * perform connection to the child */ rc = perform_connection(dev_m_in, dev_m_out, &addr, minor, child); if (rc == OK) { uds_fd_table[i].child = -1; #if DEBUG == 1 printf("(uds) [%d] {do_connect} revive %d\n", minor, child); #endif /* wake the parent (server) */ uds_fd_table[child].ready_to_revive = 1; uds_unsuspend(dev_m_in->m_source, child); } return rc; } else { #if DEBUG == 1 printf("(uds) [%d] adding to %d's backlog\n", minor, i); #endif /* tell the server were waiting to be served */ /* look for a free slot in the backlog */ rc = -1; /* to trap error */ for (j = 0; j < uds_fd_table[i].backlog_size; j++) { if (uds_fd_table[i].backlog[j] == -1) { uds_fd_table[i].backlog[j] = minor; rc = 0; break; } } if (rc == -1) { /* backlog is full */ break; } /* see if the server is blocked on select() */ if (uds_fd_table[i].selecting == 1) { /* if the server wants to know * about data ready to read and * it doesn't know about it * already, then let the server * know we have data for it. */ if ((uds_fd_table[i].sel_ops_in & SEL_RD) && !(uds_fd_table[i].sel_ops_out & SEL_RD)) { uds_fd_table[i].sel_ops_out |= SEL_RD; uds_fd_table[i].status_updated = 1; uds_unsuspend( dev_m_in->m_source, i); } } /* we found our server */ uds_fd_table[minor].peer = i; /* set the address */ memcpy(&(uds_fd_table[minor].addr), &addr, sizeof(struct sockaddr_un)); break; } } } if (uds_fd_table[minor].peer == -1) { /* could not find another open socket listening on the * specified address with room in the backlog */ return ECONNREFUSED; } #if DEBUG == 1 printf("(uds) [%d] {do_connect} suspend\n", minor); #endif /* suspend until the server side completes the connection with accept() */ uds_fd_table[minor].suspended = UDS_SUSPENDED_CONNECT; return SUSPEND; }
void handle_property_set_fd() { prop_msg msg; int s; int r; int res; struct ucred cr; struct sockaddr_un addr; socklen_t addr_size = sizeof(addr); socklen_t cr_size = sizeof(cr); char * source_ctx = NULL; if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) { return; } /* Check socket options here */ if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) { close(s); ERROR("Unable to receive socket options\n"); return; } r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0)); if(r != sizeof(prop_msg)) { ERROR("sys_prop: mis-match msg size received: %d expected: %zu errno: %d\n", r, sizeof(prop_msg), errno); close(s); return; } switch(msg.cmd) { case PROP_MSG_SETPROP: msg.name[PROP_NAME_MAX-1] = 0; msg.value[PROP_VALUE_MAX-1] = 0; if (!is_legal_property_name(msg.name, strlen(msg.name))) { ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name); close(s); return; } getpeercon(s, &source_ctx); if(memcmp(msg.name,"ctl.",4) == 0) { // Keep the old close-socket-early behavior when handling // ctl.* properties. close(s); if (check_control_perms(msg.value, cr.uid, cr.gid, source_ctx)) { handle_control_message((char*) msg.name + 4, (char*) msg.value); } else { ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n", msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid); } } else { if (check_perms(msg.name, cr.uid, cr.gid, source_ctx)) { property_set((char*) msg.name, (char*) msg.value); } else { ERROR("sys_prop: permission denied uid:%d name:%s\n", cr.uid, msg.name); } // Note: bionic's property client code assumes that the // property server will not close the socket until *AFTER* // the property is written to memory. close(s); } freecon(source_ctx); break; default: close(s); break; } }
/* * Note, an intention with return values is so that this is compatible with * ipa-getkeytab. This is so based on the return value you can distinguish * between errors common between the two (no kerbeors ccache) and those * unique (host already added). */ int main(int argc, const char **argv) { static const char *hostname = NULL; static const char *server = NULL; static const char *keytab = NULL; static const char *bindpw = NULL; static const char *basedn = NULL; int quiet = 0; int unenroll = 0; int force = 0; struct poptOption options[] = { { "debug", 'd', POPT_ARG_NONE, &debug, 0, _("Print the raw XML-RPC output in GSSAPI mode"), NULL }, { "quiet", 'q', POPT_ARG_NONE, &quiet, 0, _("Quiet mode. Only errors are displayed."), NULL }, { "unenroll", 'u', POPT_ARG_NONE, &unenroll, 0, _("Unenroll this host from IPA server"), NULL }, { "hostname", 'h', POPT_ARG_STRING, &hostname, 0, _("Hostname of this server"), _("hostname") }, { "server", 's', POPT_ARG_STRING, &server, 0, _("IPA Server to use"), _("hostname") }, { "keytab", 'k', POPT_ARG_STRING, &keytab, 0, _("Specifies where to store keytab information."), _("filename") }, { "force", 'f', POPT_ARG_NONE, &force, 0, _("Force the host join. Rejoin even if already joined."), NULL }, { "bindpw", 'w', POPT_ARG_STRING, &bindpw, 0, _("LDAP password (if not using Kerberos)"), _("password") }, { "basedn", 'b', POPT_ARG_STRING, &basedn, 0, _("LDAP basedn"), _("basedn") }, POPT_AUTOHELP POPT_TABLEEND }; poptContext pc; int ret; ret = init_gettext(); if (ret) { exit(2); } pc = poptGetContext("ipa-join", argc, (const char **)argv, options, 0); ret = poptGetNextOpt(pc); if (ret != -1) { if (!quiet) { poptPrintUsage(pc, stderr, 0); } exit(2); } poptFreeContext(pc); if (debug) setenv("XMLRPC_TRACE_XML", "1", 1); if (!keytab) keytab = "/etc/krb5.keytab"; if (unenroll) { ret = unenroll_host(server, hostname, keytab, quiet); } else { ret = check_perms(keytab); if (ret == 0) ret = join(server, hostname, bindpw, basedn, keytab, force, quiet); } exit(ret); }