Esempio n. 1
0
mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) {
    mp_int_t size = mp_obj_get_int(size_in);
    void *buf = NULL;
    if (size > 0) {
        buf = m_malloc(size);
    }

    int old_size = mp_emergency_exception_buf_size;
    void *old_buf = mp_emergency_exception_buf;

    // Update the 2 variables atomically so that an interrupt can't occur
    // between the assignments.
    mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
    mp_emergency_exception_buf_size = size;
    mp_emergency_exception_buf = buf;
    MICROPY_END_ATOMIC_SECTION(atomic_state);

    if (old_buf != NULL) {
        m_free(old_buf, old_size);
    }
    return mp_const_none;
}
Esempio n. 2
0
static char *
get_control_dir(char *cidir)
{
  if (f_noact) {
    char *tmpdir;

    tmpdir = mkdtemp(path_make_temp_template("dpkg"));
    if (tmpdir == NULL)
      ohshite(_("unable to create temporary directory"));

    cidir = m_realloc(cidir, strlen(tmpdir) + MAXCONTROLFILENAME + 10);

    strcpy(cidir, tmpdir);

    free(tmpdir);
  } else {
    const char *admindir;

    admindir = dpkg_db_get_dir();

    /* The admindir length is always constant on a dpkg execution run. */
    if (cidir == NULL)
      cidir = m_malloc(strlen(admindir) + sizeof(CONTROLDIRTMP) +
                       MAXCONTROLFILENAME + 10);

    /* We want it to be on the same filesystem so that we can
     * use rename(2) to install the postinst &c. */
    strcpy(cidir, admindir);
    strcat(cidir, "/" CONTROLDIRTMP);

    /* Make sure the control information directory is empty. */
    ensure_pathname_nonexisting(cidir);
  }

  strcat(cidir, "/");

  return cidir;
}
Esempio n. 3
0
static bool
parsestring(struct pkg_format_node *cur, const char *fmt, const char *fmtend,
            struct dpkg_error *err)
{
	int len;
	char *write;

	len = fmtend - fmt + 1;

	cur->type = PKG_FORMAT_STRING;
	write = cur->data = m_malloc(len + 1);
	while (fmt <= fmtend) {
		if (*fmt == '\\') {
			fmt++;
			switch (*fmt) {
			case 'n':
				*write = '\n';
				break;
			case 't':
				*write = '\t';
				break;
			case 'r':
				*write = '\r';
				break;
			case '\\':
			default:
				*write = *fmt;
				break;
			}
		} else
			*write = *fmt;
		write++;
		fmt++;
	}
	*write = '\0';

	return true;
}
Esempio n. 4
0
static int
parsefield(struct lstitem *cur, const char *fmt, const char *fmtend)
{
	int len;
	const char *ws;

	len = fmtend - fmt + 1;

	ws = memchr(fmt, ';', len);
	if (ws) {
		char *endptr;
		long w;

		w = strtol(ws + 1, &endptr, 0);
		if (endptr[0] != '}') {
			fprintf(stderr,
			        _("invalid character `%c' in field width\n"),
			       *endptr);
			return 0;
		}

		if (w < 0) {
			cur->pad = 1;
			cur->width = (size_t)-w;
		} else
			cur->width = (size_t)w;

		len = ws - fmt;
	}

	cur->type = field;
	cur->data = m_malloc(len + 1);
	memcpy(cur->data, fmt, len);
	cur->data[len] = '\0';

	return 1;
}
Esempio n. 5
0
static int
parsestring(struct lstitem *cur, const char *fmt, const char *fmtend)
{
	int len;
	char *write;

	len = fmtend - fmt + 1;

	cur->type = string;
	write = cur->data = m_malloc(len + 1);
	while (fmt <= fmtend) {
		if (*fmt == '\\') {
			fmt++;
			switch (*fmt) {
			case 'n':
				*write = '\n';
				break;
			case 't':
				*write = '\t';
				break;
			case 'r':
				*write = '\r';
				break;
			case '\\':
			default:
				*write = *fmt;
				break;
			}
		} else
			*write = *fmt;
		write++;
		fmt++;
	}
	*write = '\0';

	return 1;
}
Esempio n. 6
0
/* non-blocking function writing out a current encrypted packet */
void write_packet() {

	int len, written;
	buffer * writebuf = NULL;
	time_t now;
	unsigned packet_type;
	int all_ignore = 1;
#ifdef HAVE_WRITEV
	struct iovec *iov = NULL;
	int i;
	struct Link *l;
#endif
	
	TRACE2(("enter write_packet"))
	dropbear_assert(!isempty(&ses.writequeue));

#ifdef HAVE_WRITEV
	iov = m_malloc(sizeof(*iov) * ses.writequeue.count);
	for (l = ses.writequeue.head, i = 0; l; l = l->link, i++)
	{
		writebuf = (buffer*)l->item;
		packet_type = writebuf->data[writebuf->len-1];
		len = writebuf->len - 1 - writebuf->pos;
		dropbear_assert(len > 0);
		all_ignore &= (packet_type == SSH_MSG_IGNORE);
		TRACE2(("write_packet writev #%d  type %d len %d/%d", i, packet_type,
				len, writebuf->len-1))
		iov[i].iov_base = buf_getptr(writebuf, len);
		iov[i].iov_len = len;
	}
	written = writev(ses.sock_out, iov, ses.writequeue.count);
	if (written < 0) {
		if (errno == EINTR) {
			m_free(iov);
			TRACE2(("leave writepacket: EINTR"))
			return;
		} else {
Esempio n. 7
0
/* set up a session channel */
void newchansess(struct Channel *channel) {

	struct ChanSess *chansess;

	assert(channel->typedata == NULL);

	chansess = (struct ChanSess*)m_malloc(sizeof(struct ChanSess));
	chansess->cmd = NULL;
	chansess->pid = 0;

	/* pty details */
	chansess->master = -1;
	chansess->slave = -1;
	chansess->tty = NULL;
	chansess->term = NULL;
	chansess->termw = 0;
	chansess->termh = 0;
	chansess->termc = 0;
	chansess->termr = 0;

	chansess->exited = 0;

	channel->typedata = chansess;

#ifndef DISABLE_X11FWD
	chansess->x11fd = -1;
	chansess->x11authprot = NULL;
	chansess->x11authcookie = NULL;
#endif

#ifndef DISABLE_AGENTFWD
	chansess->agentfd = -1;
	chansess->agentfile = NULL;
	chansess->agentdir = NULL;
#endif

}
Esempio n. 8
0
File: tarfn.c Progetto: smcv/dpkg
/**
 * Decode a GNU longlink or longname from the tar archive.
 *
 * The way the GNU long{link,name} stuff works is like this:
 *
 * - The first header is a “dummy” header that contains the size of the
 *   filename.
 * - The next N headers contain the filename.
 * - After the headers with the filename comes the “real” header with a
 *   bogus name or link.
 */
static int
tar_gnu_long(void *ctx, const struct tar_operations *ops, struct tar_entry *te,
             char **longp)
{
	char buf[TARBLKSZ];
	char *bp;
	int status = 0;
	int long_read;

	free(*longp);
	*longp = bp = m_malloc(te->size);

	for (long_read = te->size; long_read > 0; long_read -= TARBLKSZ) {
		int copysize;

		status = ops->read(ctx, buf, TARBLKSZ);
		if (status == TARBLKSZ)
			status = 0;
		else {
			/* Read partial header record? */
			if (status > 0) {
				errno = 0;
				status = -1;
			}

			/* If we didn't get TARBLKSZ bytes read, punt. */
			break;
		}

		copysize = min(long_read, TARBLKSZ);
		memcpy(bp, buf, copysize);
		bp += copysize;
	};

	return status;
}
Esempio n. 9
0
void create_fdlg( FarDialog *fdlg, int X, int Y, int Title, struct InitDialogItem *Item, int number )
{
	fdlg->itemsNumber = number + 1;
	fdlg->di = (FarDialogItem *)m_malloc( sizeof(FarDialogItem)*fdlg->itemsNumber );

	fdlg->X = X;
	fdlg->Y = Y;

	struct FarDialogItem *pi = fdlg->di;
	const struct InitDialogItem *ps = Item;
	int i;

	pi->Type = DI_DOUBLEBOX;
	pi->X1 = 3; pi->Y1 = 1; pi->X2 = X - 4; pi->Y2 = Y - 2;
	strcpy( pi->Data, MSG(Title) );

	for( i = 0, pi++; i < number; i++, pi++, ps++ ) {

		pi->Type = ps->Type;
		pi->X1 = ps->X1 >= 0 ? ps->X1 + 4 : X - 4 + ps->X1 ;
		pi->Y1 = ps->Y1 >= 0 ? ps->Y1 + 2 : Y - 2 + ps->Y1 ;
		pi->X2 = ps->X2 >= 0 ? ps->X2 + 4 : X - 4 + ps->X2 ;
		pi->Y2 = ps->Y2 >= 0 ? ps->Y2 + 2 : Y - 2 + ps->Y2 ;
		pi->Focus = ps->Focus;
		pi->Selected = ps->Selected;
		pi->Flags = ps->Flags;
		pi->DefaultButton = ps->DefaultButton;
		if( (unsigned int)ps->Data < 2000 )
			strcpy( pi->Data, MSG((unsigned int)ps->Data) );
		else
			strcpy( pi->Data, ps->Data );

		if( ps->position )
			*ps->position = i+1;
	}
}
Esempio n. 10
0
/**
 * Compute the screen width of a string.
 *
 * @param str The multibyte string.
 *
 * @return The width of the string.
 */
int
str_width(const char *str)
{
#ifdef ENABLE_NLS
	mbstate_t state;
	wchar_t *wcs;
	const char *mbs = str;
	size_t len, res;
	int width;

	len = strlen(str) + 1;
	wcs = m_malloc(sizeof(wcs[0]) * len);

	memset(&state, 0, sizeof(state));

	res = mbsrtowcs(wcs, &mbs, len, &state);
	if (res == (size_t)-1) {
#ifdef DPKG_UNIFORM_ENCODING
		ohshit(_("cannot convert multibyte string '%s' "
		         "to a wide-character string"), str);
#else
		/* Cannot convert, fallback to ASCII method. */
		free(wcs);
		return strlen(str);
#endif
	}

	width = wcswidth(wcs, res);

	free(wcs);

	return width;
#else
	return strlen(str);
#endif
}
Esempio n. 11
0
void
pkg_hash_report(FILE *file)
{
  int i, c;
  struct pkgset *pkg;
  int *freq;
  int empty = 0, used = 0, collided = 0;

  freq = m_malloc(sizeof(int) * nset + 1);
  for (i = 0; i <= nset; i++)
    freq[i] = 0;
  for (i=0; i<BINS; i++) {
    for (c=0, pkg= bins[i]; pkg; c++, pkg= pkg->next);
    fprintf(file, "pkg-hash: bin %5d has %7d\n", i, c);
    if (c == 0)
      empty++;
    else if (c == 1)
      used++;
    else {
      used++;
      collided++;
    }
    freq[c]++;
  }
  for (i = nset; i > 0 && freq[i] == 0; i--);
  while (i >= 0) {
    fprintf(file, "pkg-hash: size %7d occurs %5d times\n", i, freq[i]);
    i--;
  }
  fprintf(file, "pkg-hash: bins empty %d\n", empty);
  fprintf(file, "pkg-hash: bins used %d (collided %d)\n", used, collided);

  m_output(file, "<hash report>");

  free(freq);
}
Esempio n. 12
0
dss_key * gen_dss_priv_key(unsigned int size) {

	dss_key *key;

	key = (dss_key*)m_malloc(sizeof(dss_key));

	key->p = (mp_int*)m_malloc(sizeof(mp_int));
	key->q = (mp_int*)m_malloc(sizeof(mp_int));
	key->g = (mp_int*)m_malloc(sizeof(mp_int));
	key->y = (mp_int*)m_malloc(sizeof(mp_int));
	key->x = (mp_int*)m_malloc(sizeof(mp_int));
	m_mp_init_multi(key->p, key->q, key->g, key->y, key->x, NULL);
	
	seedrandom();
	
	getq(key);
	getp(key, size);
	getg(key);
	getx(key);
	gety(key);

	return key;
	
}
Esempio n. 13
0
void cli_getopts(int argc, char ** argv) {
	unsigned int i, j;
	char ** next = 0;
	enum {
		OPT_EXTENDED_OPTIONS,
#ifdef ENABLE_CLI_PUBKEY_AUTH
		OPT_AUTHKEY,
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
		OPT_LOCALTCPFWD,
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
		OPT_REMOTETCPFWD,
#endif
#ifdef ENABLE_CLI_NETCAT
		OPT_NETCAT,
#endif
		/* a flag (no arg) if 'next' is NULL, a string-valued option otherwise */
		OPT_OTHER
	} opt;
	unsigned int cmdlen;
	char* dummy = NULL; /* Not used for anything real */

	char* recv_window_arg = NULL;
	char* keepalive_arg = NULL;
	char* idle_timeout_arg = NULL;
	char *host_arg = NULL;
	char c;

	/* see printhelp() for options */
	cli_opts.progname = argv[0];
	cli_opts.remotehost = NULL;
	cli_opts.remoteport = NULL;
	cli_opts.username = NULL;
	cli_opts.cmd = NULL;
	cli_opts.no_cmd = 0;
	cli_opts.backgrounded = 0;
	cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
	cli_opts.always_accept_key = 0;
	cli_opts.no_hostkey_check = 0;
	cli_opts.is_subsystem = 0;
#ifdef ENABLE_CLI_PUBKEY_AUTH
	cli_opts.privkeys = list_new();
#endif
#ifdef ENABLE_CLI_ANYTCPFWD
	cli_opts.exit_on_fwd_failure = 0;
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
	cli_opts.localfwds = list_new();
	opts.listen_fwd_all = 0;
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
	cli_opts.remotefwds = list_new();
#endif
#ifdef ENABLE_CLI_AGENTFWD
	cli_opts.agent_fwd = 0;
	cli_opts.agent_fd = -1;
	cli_opts.agent_keys_loaded = 0;
#endif
#ifdef ENABLE_CLI_PROXYCMD
	cli_opts.proxycmd = NULL;
#endif
#ifndef DISABLE_ZLIB
	opts.compress_mode = DROPBEAR_COMPRESS_ON;
#endif
#ifdef ENABLE_USER_ALGO_LIST
	opts.cipher_list = NULL;
	opts.mac_list = NULL;
#endif
#ifndef DISABLE_SYSLOG
	opts.usingsyslog = 0;
#endif
	cli_opts.ipfamily = AF_UNSPEC;
	opts.recv_window = DEFAULT_RECV_WINDOW;
	opts.keepalive_secs = DEFAULT_KEEPALIVE;
	opts.idle_timeout_secs = DEFAULT_IDLE_TIMEOUT;

	fill_own_user();

	for (i = 1; i < (unsigned int)argc; i++) {
		/* Handle non-flag arguments such as hostname or commands for the remote host */
		if (argv[i][0] != '-')
		{
			if (host_arg == NULL) {
				host_arg = argv[i];
			continue;
		}
			/* Commands to pass to the remote host. No more flag handling,
			commands are consumed below */
			break;
		}

		/* Begins with '-' */
		opt = OPT_OTHER;
		for (j = 1; (c = argv[i][j]) != '\0' && !next && opt == OPT_OTHER; j++) {
			switch (c) {
				case 'y': /* always accept the remote hostkey */
					if (cli_opts.always_accept_key) {
						/* twice means no checking at all */
						cli_opts.no_hostkey_check = 1;
					}
					cli_opts.always_accept_key = 1;
					break;
#if defined AF_INET6 && AF_INET6 < AF_MAX
				case '4':
					cli_opts.ipfamily = AF_INET;
					break;
				case '6':
					cli_opts.ipfamily = AF_INET6;
					break;
#endif
				case 'p': /* remoteport */
					next = &cli_opts.remoteport;
					break;
#ifdef ENABLE_CLI_PUBKEY_AUTH
				case 'i': /* an identityfile */
					opt = OPT_AUTHKEY;
					break;
#endif
				case 't': /* we want a pty */
					cli_opts.wantpty = 1;
					break;
				case 'T': /* don't want a pty */
					cli_opts.wantpty = 0;
					break;
				case 'N':
					cli_opts.no_cmd = 1;
					break;
				case 'f':
					cli_opts.backgrounded = 1;
					break;
				case 's':
					cli_opts.is_subsystem = 1;
					break;
				case 'o':
					opt = OPT_EXTENDED_OPTIONS;
					break;
#ifdef ENABLE_CLI_LOCALTCPFWD
				case 'L':
					opt = OPT_LOCALTCPFWD;
					break;
				case 'g':
					opts.listen_fwd_all = 1;
					break;
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
				case 'R':
					opt = OPT_REMOTETCPFWD;
					break;
#endif
#ifdef ENABLE_CLI_NETCAT
				case 'B':
					opt = OPT_NETCAT;
					break;
#endif
#ifdef ENABLE_CLI_PROXYCMD
				case 'J':
					next = &cli_opts.proxycmd;
					break;
#endif
				case 'l':
					next = &cli_opts.username;
					break;
				case 'h':
					printhelp();
					exit(EXIT_SUCCESS);
					break;
				case 'u':
					/* backwards compatibility with old urandom option */
					break;
				case 'W':
					next = &recv_window_arg;
					break;
				case 'K':
					next = &keepalive_arg;
					break;
				case 'I':
					next = &idle_timeout_arg;
					break;
#ifdef ENABLE_CLI_AGENTFWD
				case 'A':
					cli_opts.agent_fwd = 1;
					break;
#endif
#ifdef ENABLE_USER_ALGO_LIST
				case 'c':
					next = &opts.cipher_list;
					break;
				case 'm':
					next = &opts.mac_list;
					break;
#endif
#ifdef DEBUG_TRACE
				case 'v':
					debug_trace = 1;
					break;
#endif
				case 'F':
				case 'e':
#ifndef ENABLE_USER_ALGO_LIST
				case 'c':
				case 'm':
#endif
				case 'D':
#ifndef ENABLE_CLI_REMOTETCPFWD
				case 'R':
#endif
#ifndef ENABLE_CLI_LOCALTCPFWD
				case 'L':
#endif
				case 'V':
					print_version();
					exit(EXIT_SUCCESS);
					break;
				case 'b':
					next = &dummy;
					/* FALLTHROUGH */
				default:
					fprintf(stderr, 
						"WARNING: Ignoring unknown option -%c\n", c);
					break;
			} /* Switch */
			}

		if (!next && opt == OPT_OTHER) /* got a flag */
			continue;

		if (c == '\0') {
			i++;
			j = 0;
			if (!argv[i])
				dropbear_exit("Missing argument");
		}

		if (opt == OPT_EXTENDED_OPTIONS) {
			TRACE(("opt extended"))
			add_extendedopt(&argv[i][j]);
		}
		else
#ifdef ENABLE_CLI_PUBKEY_AUTH
		if (opt == OPT_AUTHKEY) {
			TRACE(("opt authkey"))
			loadidentityfile(&argv[i][j], 1);
		}
		else
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
		if (opt == OPT_REMOTETCPFWD) {
			TRACE(("opt remotetcpfwd"))
			addforward(&argv[i][j], cli_opts.remotefwds);
		}
		else
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
		if (opt == OPT_LOCALTCPFWD) {
			TRACE(("opt localtcpfwd"))
			addforward(&argv[i][j], cli_opts.localfwds);
		}
		else
#endif
#ifdef ENABLE_CLI_NETCAT
		if (opt == OPT_NETCAT) {
			TRACE(("opt netcat"))
			add_netcat(&argv[i][j]);
		}
		else
#endif
		if (next) {
			/* The previous flag set a value to assign */
			*next = &argv[i][j];
			if (*next == NULL)
				dropbear_exit("Invalid null argument");
			next = NULL;
		}
	}

	/* Done with options/flags; now handle the hostname (which may not
	 * start with a hyphen) and optional command */

	if (host_arg == NULL) { /* missing hostname */
		printhelp();
		exit(EXIT_FAILURE);
	}
	TRACE(("host is: %s", host_arg))

	if (i < (unsigned int)argc) {
		/* Build the command to send */
				cmdlen = 0;
		for (j = i; j < (unsigned int)argc; j++)
					cmdlen += strlen(argv[j]) + 1; /* +1 for spaces */

				/* Allocate the space */
				cli_opts.cmd = (char*)m_malloc(cmdlen);
				cli_opts.cmd[0] = '\0';

				/* Append all the bits */
				for (j = i; j < (unsigned int)argc; j++) {
					strlcat(cli_opts.cmd, argv[j], cmdlen);
					strlcat(cli_opts.cmd, " ", cmdlen);
				}
				/* It'll be null-terminated here */
		TRACE(("cmd is: %s", cli_opts.cmd))
	}
Esempio n. 14
0
/* Listen on address:port. 
 * Special cases are address of "" listening on everything,
 * and address of NULL listening on localhost only.
 * Returns the number of sockets bound on success, or -1 on failure. On
 * failure, if errstring wasn't NULL, it'll be a newly malloced error
 * string.*/
int dropbear_listen(const char* address, const char* port,
		int *socks, unsigned int sockcount, char **errstring, int *maxfd) {

	struct addrinfo hints, *res = NULL, *res0 = NULL;
	int err;
	unsigned int nsock;
	struct linger linger;
	int val;
	int sock;

	TRACE(("enter dropbear_listen"))
	
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */
	hints.ai_socktype = SOCK_STREAM;

	/* for calling getaddrinfo:
	 address == NULL and !AI_PASSIVE: local loopback
	 address == NULL and AI_PASSIVE: all interfaces
	 address != NULL: whatever the address says */
	if (!address) {
		TRACE(("dropbear_listen: local loopback"))
	} else {
		if (address[0] == '\0') {
			TRACE(("dropbear_listen: all interfaces"))
			address = NULL;
		}
		hints.ai_flags = AI_PASSIVE;
	}
	err = getaddrinfo(address, port, &hints, &res0);

	if (err) {
		if (errstring != NULL && *errstring == NULL) {
			int len;
			len = 20 + strlen(gai_strerror(err));
			*errstring = (char*)m_malloc(len);
			snprintf(*errstring, len, "Error resolving: %s", gai_strerror(err));
		}
		if (res0) {
			freeaddrinfo(res0);
			res0 = NULL;
		}
		TRACE(("leave dropbear_listen: failed resolving"))
		return -1;
	}


	nsock = 0;
	for (res = res0; res != NULL && nsock < sockcount;
			res = res->ai_next) {

		/* Get a socket */
		socks[nsock] = socket(res->ai_family, res->ai_socktype,
				res->ai_protocol);

		sock = socks[nsock]; /* For clarity */

		if (sock < 0) {
			err = errno;
			TRACE(("socket() failed"))
			continue;
		}

		/* Various useful socket options */
		val = 1;
		/* set to reuse, quick timeout */
		setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof(val));
		linger.l_onoff = 1;
		linger.l_linger = 5;
		setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger));

#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
		if (res->ai_family == AF_INET6) {
			int on = 1;
			if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, 
						&on, sizeof(on)) == -1) {
				dropbear_log(LOG_WARNING, "Couldn't set IPV6_V6ONLY");
			}
		}
#endif

		set_sock_priority(sock);

		if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
			err = errno;
			close(sock);
			TRACE(("bind(%s) failed", port))
			continue;
		}
Esempio n. 15
0
/* called only at the start of a session, set up initial state */
void common_session_init(int sock_in, int sock_out) {
	time_t now;

#ifdef DEBUG_TRACE
	debug_start_net();
#endif

	TRACE(("enter session_init"))

	ses.sock_in = sock_in;
	ses.sock_out = sock_out;
	ses.maxfd = MAX(sock_in, sock_out);

	if (sock_in >= 0) {
		setnonblocking(sock_in);
	}
	if (sock_out >= 0) {
		setnonblocking(sock_out);
	}

	ses.socket_prio = DROPBEAR_PRIO_DEFAULT;
	/* Sets it to lowdelay */
	update_channel_prio();

	now = monotonic_now();
	ses.connect_time = now;
	ses.last_packet_time_keepalive_recv = now;
	ses.last_packet_time_idle = now;
	ses.last_packet_time_any_sent = 0;
	ses.last_packet_time_keepalive_sent = 0;
	
	if (pipe(ses.signal_pipe) < 0) {
		dropbear_exit("Signal pipe failed");
	}
	setnonblocking(ses.signal_pipe[0]);
	setnonblocking(ses.signal_pipe[1]);

	ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[0]);
	ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[1]);
	
	ses.writepayload = buf_new(TRANS_MAX_PAYLOAD_LEN);
	ses.transseq = 0;

	ses.readbuf = NULL;
	ses.payload = NULL;
	ses.recvseq = 0;

	initqueue(&ses.writequeue);

	ses.requirenext = SSH_MSG_KEXINIT;
	ses.dataallowed = 1; /* we can send data until we actually 
							send the SSH_MSG_KEXINIT */
	ses.ignorenext = 0;
	ses.lastpacket = 0;
	ses.reply_queue_head = NULL;
	ses.reply_queue_tail = NULL;

	/* set all the algos to none */
	ses.keys = (struct key_context*)m_malloc(sizeof(struct key_context));
	ses.newkeys = NULL;
	ses.keys->recv.algo_crypt = &dropbear_nocipher;
	ses.keys->trans.algo_crypt = &dropbear_nocipher;
	ses.keys->recv.crypt_mode = &dropbear_mode_none;
	ses.keys->trans.crypt_mode = &dropbear_mode_none;
	
	ses.keys->recv.algo_mac = &dropbear_nohash;
	ses.keys->trans.algo_mac = &dropbear_nohash;

	ses.keys->algo_kex = NULL;
	ses.keys->algo_hostkey = -1;
	ses.keys->recv.algo_comp = DROPBEAR_COMP_NONE;
	ses.keys->trans.algo_comp = DROPBEAR_COMP_NONE;

#ifndef DISABLE_ZLIB
	ses.keys->recv.zstream = NULL;
	ses.keys->trans.zstream = NULL;
#endif

	/* key exchange buffers */
	ses.session_id = NULL;
	ses.kexhashbuf = NULL;
	ses.transkexinit = NULL;
	ses.dh_K = NULL;
	ses.remoteident = NULL;

	ses.chantypes = NULL;

	ses.allowprivport = 0;

	TRACE(("leave session_init"))
}
Esempio n. 16
0
void
extracthalf(const char *debar, const char *dir,
            enum dpkg_tar_options taroption, int admininfo)
{
  struct dpkg_error err;
  const char *errstr;
  char versionbuf[40];
  struct deb_version version;
  off_t ctrllennum, memberlen = 0;
  ssize_t r;
  int dummy;
  pid_t c1=0,c2,c3;
  int p1[2], p2[2];
  int p2_out;
  int arfd;
  struct stat stab;
  char nlc;
  int adminmember = -1;
  bool header_done;
  enum compressor_type decompressor = COMPRESSOR_TYPE_GZIP;

  if (strcmp(debar, "-") == 0)
    arfd = STDIN_FILENO;
  else
    arfd = open(debar, O_RDONLY);
  if (arfd < 0)
    ohshite(_("failed to read archive '%.255s'"), debar);
  if (fstat(arfd, &stab))
    ohshite(_("failed to fstat archive"));

  r = read_line(arfd, versionbuf, strlen(DPKG_AR_MAGIC), sizeof(versionbuf) - 1);
  if (r < 0)
    read_fail(r, debar, _("archive magic version number"));

  if (strcmp(versionbuf, DPKG_AR_MAGIC) == 0) {
    ctrllennum= 0;
    header_done = false;
    for (;;) {
      struct ar_hdr arh;

      r = fd_read(arfd, &arh, sizeof(arh));
      if (r != sizeof(arh))
        read_fail(r, debar, _("archive member header"));

      dpkg_ar_normalize_name(&arh);

      if (dpkg_ar_member_is_illegal(&arh))
        ohshit(_("file '%.250s' is corrupt - bad archive header magic"), debar);
      memberlen = dpkg_ar_member_get_size(debar, &arh);
      if (!header_done) {
        char *infobuf;

        if (strncmp(arh.ar_name, DEBMAGIC, sizeof(arh.ar_name)) != 0)
          ohshit(_("file '%.250s' is not a debian binary archive (try dpkg-split?)"),
                 debar);
        infobuf= m_malloc(memberlen+1);
        r = fd_read(arfd, infobuf, memberlen + (memberlen & 1));
        if (r != (memberlen + (memberlen & 1)))
          read_fail(r, debar, _("archive information header member"));
        infobuf[memberlen] = '\0';

        if (strchr(infobuf, '\n') == NULL)
          ohshit(_("archive has no newlines in header"));
        errstr = deb_version_parse(&version, infobuf);
        if (errstr)
          ohshit(_("archive has invalid format version: %s"), errstr);
        if (version.major != 2)
          ohshit(_("archive is format version %d.%d; get a newer dpkg-deb"),
                 version.major, version.minor);

        free(infobuf);

        header_done = true;
      } else if (arh.ar_name[0] == '_') {
        /* Members with ‘_’ are noncritical, and if we don't understand
         * them we skip them. */
        if (fd_skip(arfd, memberlen + (memberlen & 1), &err) < 0)
          ohshit(_("cannot skip archive member from '%s': %s"), debar, err.str);
      } else {
        if (strncmp(arh.ar_name, ADMINMEMBER, strlen(ADMINMEMBER)) == 0) {
          const char *extension = arh.ar_name + strlen(ADMINMEMBER);

	  adminmember = 1;
          decompressor = compressor_find_by_extension(extension);
          if (decompressor != COMPRESSOR_TYPE_NONE &&
              decompressor != COMPRESSOR_TYPE_GZIP &&
              decompressor != COMPRESSOR_TYPE_XZ)
            ohshit(_("archive '%s' uses unknown compression for member '%.*s', "
                     "giving up"),
                   debar, (int)sizeof(arh.ar_name), arh.ar_name);
        } else {
          if (adminmember != 1)
            ohshit(_("archive '%s' has premature member '%.*s' before '%s', "
                     "giving up"),
                   debar, (int)sizeof(arh.ar_name), arh.ar_name, ADMINMEMBER);

	  if (strncmp(arh.ar_name, DATAMEMBER, strlen(DATAMEMBER)) == 0) {
	    const char *extension = arh.ar_name + strlen(DATAMEMBER);

	    adminmember= 0;
	    decompressor = compressor_find_by_extension(extension);
            if (decompressor == COMPRESSOR_TYPE_UNKNOWN)
              ohshit(_("archive '%s' uses unknown compression for member '%.*s', "
                       "giving up"),
                     debar, (int)sizeof(arh.ar_name), arh.ar_name);
          } else {
            ohshit(_("archive '%s' has premature member '%.*s' before '%s', "
                     "giving up"),
                   debar, (int)sizeof(arh.ar_name), arh.ar_name, DATAMEMBER);
          }
        }
        if (adminmember == 1) {
          if (ctrllennum != 0)
            ohshit(_("archive '%.250s' contains two control members, giving up"),
                   debar);
          ctrllennum= memberlen;
        }
        if (!adminmember != !admininfo) {
          if (fd_skip(arfd, memberlen + (memberlen & 1), &err) < 0)
            ohshit(_("cannot skip archive member from '%s': %s"), debar, err.str);
        } else {
          /* Yes! - found it. */
          break;
        }
      }
    }

    if (admininfo >= 2) {
      printf(_(" new debian package, version %d.%d.\n"
               " size %jd bytes: control archive=%jd bytes.\n"),
             version.major, version.minor,
             (intmax_t)stab.st_size, (intmax_t)ctrllennum);
      m_output(stdout, _("<standard output>"));
    }
  } else if (strncmp(versionbuf, "0.93", 4) == 0) {
    char ctrllenbuf[40];
    int l;

    l = strlen(versionbuf);

    if (strchr(versionbuf, '\n') == NULL)
      ohshit(_("archive has no newlines in header"));
    errstr = deb_version_parse(&version, versionbuf);
    if (errstr)
      ohshit(_("archive has invalid format version: %s"), errstr);

    r = read_line(arfd, ctrllenbuf, 1, sizeof(ctrllenbuf) - 1);
    if (r < 0)
      read_fail(r, debar, _("archive control member size"));
    if (sscanf(ctrllenbuf, "%jd%c%d", &ctrllennum, &nlc, &dummy) != 2 ||
        nlc != '\n')
      ohshit(_("archive has malformatted control member size '%s'"), ctrllenbuf);

    if (admininfo) {
      memberlen = ctrllennum;
    } else {
      memberlen = stab.st_size - ctrllennum - strlen(ctrllenbuf) - l;
      if (fd_skip(arfd, ctrllennum, &err) < 0)
        ohshit(_("cannot skip archive control member from '%s': %s"), debar,
               err.str);
    }

    if (admininfo >= 2) {
      printf(_(" old debian package, version %d.%d.\n"
               " size %jd bytes: control archive=%jd, main archive=%jd.\n"),
             version.major, version.minor,
             (intmax_t)stab.st_size, (intmax_t)ctrllennum,
             (intmax_t)(stab.st_size - ctrllennum - strlen(ctrllenbuf) - l));
      m_output(stdout, _("<standard output>"));
    }
  } else {
    if (strncmp(versionbuf, "!<arch>", 7) == 0) {
      notice(_("file looks like it might be an archive which has been\n"
               " corrupted by being downloaded in ASCII mode"));
    }

    ohshit(_("'%.255s' is not a debian format archive"), debar);
  }

  m_pipe(p1);
  c1 = subproc_fork();
  if (!c1) {
    close(p1[0]);
    if (fd_fd_copy(arfd, p1[1], memberlen, &err) < 0)
      ohshit(_("cannot copy archive member from '%s' to decompressor pipe: %s"),
             debar, err.str);
    if (close(p1[1]))
      ohshite(_("cannot close decompressor pipe"));
    exit(0);
  }
  close(p1[1]);

  if (taroption) {
    m_pipe(p2);
    p2_out = p2[1];
  } else {
    p2_out = 1;
  }

  c2 = subproc_fork();
  if (!c2) {
    if (taroption)
      close(p2[0]);
    decompress_filter(decompressor, p1[0], p2_out,
                      _("decompressing archive member"));
    exit(0);
  }
  close(p1[0]);
  close(arfd);
  if (taroption) close(p2[1]);

  if (taroption) {
    c3 = subproc_fork();
    if (!c3) {
      struct command cmd;

      command_init(&cmd, TAR, "tar");
      command_add_arg(&cmd, "tar");

      if ((taroption & DPKG_TAR_LIST) && (taroption & DPKG_TAR_EXTRACT))
        command_add_arg(&cmd, "-xv");
      else if (taroption & DPKG_TAR_EXTRACT)
        command_add_arg(&cmd, "-x");
      else if (taroption & DPKG_TAR_LIST)
        command_add_arg(&cmd, "-tv");
      else
        internerr("unknown or missing tar action '%d'", taroption);

      if (taroption & DPKG_TAR_PERMS)
        command_add_arg(&cmd, "-p");
      if (taroption & DPKG_TAR_NOMTIME)
        command_add_arg(&cmd, "-m");

      command_add_arg(&cmd, "-f");
      command_add_arg(&cmd, "-");
      command_add_arg(&cmd, "--warning=no-timestamp");

      m_dup2(p2[0],0);
      close(p2[0]);

      unsetenv("TAR_OPTIONS");

      if (dir) {
        if (chdir(dir)) {
          if (errno != ENOENT)
            ohshite(_("failed to chdir to directory"));

          if (mkdir(dir, 0777))
            ohshite(_("failed to create directory"));
          if (chdir(dir))
            ohshite(_("failed to chdir to directory after creating it"));
        }
      }

      command_exec(&cmd);
    }
    close(p2[0]);
    subproc_reap(c3, "tar", 0);
  }

  subproc_reap(c2, _("<decompress>"), SUBPROC_NOPIPE);
  if (c1 != -1)
    subproc_reap(c1, _("paste"), 0);
  if (version.major == 0 && admininfo) {
    /* Handle the version as a float to preserve the behaviour of old code,
     * because even if the format is defined to be padded by 0's that might
     * not have been always true for really ancient versions... */
    while (version.minor && (version.minor % 10) == 0)
      version.minor /= 10;

    if (version.minor ==  931)
      movecontrolfiles(OLDOLDDEBDIR);
    else if (version.minor == 932 || version.minor == 933)
      movecontrolfiles(OLDDEBDIR);
  }
}
Esempio n. 17
0
/* Parse pubkey options and set ses.authstate.pubkey_options accordingly.
 * Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */
int svr_add_pubkey_options(buffer *options_buf, int line_num, const char* filename) {
    int ret = DROPBEAR_FAILURE;

    TRACE(("enter addpubkeyoptions"))

    ses.authstate.pubkey_options = (struct PubKeyOptions*)m_malloc(sizeof( struct PubKeyOptions ));

    buf_setpos(options_buf, 0);
    while (options_buf->pos < options_buf->len) {
        if (match_option(options_buf, "no-port-forwarding") == DROPBEAR_SUCCESS) {
            dropbear_log(LOG_WARNING, "Port forwarding disabled.");
            ses.authstate.pubkey_options->no_port_forwarding_flag = 1;
            goto next_option;
        }
#ifdef ENABLE_SVR_AGENTFWD
        if (match_option(options_buf, "no-agent-forwarding") == DROPBEAR_SUCCESS) {
            dropbear_log(LOG_WARNING, "Agent forwarding disabled.");
            ses.authstate.pubkey_options->no_agent_forwarding_flag = 1;
            goto next_option;
        }
#endif
#ifdef ENABLE_X11FWD
        if (match_option(options_buf, "no-X11-forwarding") == DROPBEAR_SUCCESS) {
            dropbear_log(LOG_WARNING, "X11 forwarding disabled.");
            ses.authstate.pubkey_options->no_x11_forwarding_flag = 1;
            goto next_option;
        }
#endif
        if (match_option(options_buf, "no-pty") == DROPBEAR_SUCCESS) {
            dropbear_log(LOG_WARNING, "Pty allocation disabled.");
            ses.authstate.pubkey_options->no_pty_flag = 1;
            goto next_option;
        }
        if (match_option(options_buf, "command=\"") == DROPBEAR_SUCCESS) {
            int escaped = 0;
            const unsigned char* command_start = buf_getptr(options_buf, 0);
            while (options_buf->pos < options_buf->len) {
                const char c = buf_getbyte(options_buf);
                if (!escaped && c == '"') {
                    const int command_len = buf_getptr(options_buf, 0) - command_start;
                    ses.authstate.pubkey_options->forced_command = m_malloc(command_len);
                    memcpy(ses.authstate.pubkey_options->forced_command,
                           command_start, command_len-1);
                    ses.authstate.pubkey_options->forced_command[command_len-1] = '\0';
                    dropbear_log(LOG_WARNING, "Forced command '%s'",
                                 ses.authstate.pubkey_options->forced_command);
                    goto next_option;
                }
                escaped = (!escaped && c == '\\');
            }
            dropbear_log(LOG_WARNING, "Badly formatted command= authorized_keys option");
            goto bad_option;
        }

next_option:
        /*
         * Skip the comma, and move to the next option
         * (or break out if there are no more).
         */
        if (options_buf->pos < options_buf->len
                && buf_getbyte(options_buf) != ',') {
            goto bad_option;
        }
        /* Process the next option. */
    }
    /* parsed all options with no problem */
    ret = DROPBEAR_SUCCESS;
    goto end;

bad_option:
    ret = DROPBEAR_FAILURE;
    m_free(ses.authstate.pubkey_options);
    ses.authstate.pubkey_options = NULL;
    dropbear_log(LOG_WARNING, "Bad public key options at %s:%d", filename, line_num);

end:
    TRACE(("leave addpubkeyoptions"))
    return ret;
}
Esempio n. 18
0
/* if skip_exist is set it will silently return if the key file exists */
int signkey_generate(enum signkey_type keytype, int bits, const char* filename, int skip_exist)
{
	sign_key * key = NULL;
	buffer *buf = NULL;
	char *fn_temp = NULL;
	int ret = DROPBEAR_FAILURE;
	bits = signkey_generate_get_bits(keytype, bits);

	/* now we can generate the key */
	key = new_sign_key();

	seedrandom();

	switch(keytype) {
#if DROPBEAR_RSA
		case DROPBEAR_SIGNKEY_RSA:
			key->rsakey = gen_rsa_priv_key(bits);
			break;
#endif
#if DROPBEAR_DSS
		case DROPBEAR_SIGNKEY_DSS:
			key->dsskey = gen_dss_priv_key(bits);
			break;
#endif
#if DROPBEAR_ECDSA
		case DROPBEAR_SIGNKEY_ECDSA_KEYGEN:
		case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
		case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
		case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
			{
				ecc_key *ecckey = gen_ecdsa_priv_key(bits);
				keytype = ecdsa_signkey_type(ecckey);
				*signkey_key_ptr(key, keytype) = ecckey;
			}
			break;
#endif
		default:
			dropbear_exit("Internal error");
	}

	seedrandom();

	buf = buf_new(MAX_PRIVKEY_SIZE); 

	buf_put_priv_key(buf, key, keytype);
	sign_key_free(key);
	key = NULL;
	buf_setpos(buf, 0);

	fn_temp = m_malloc(strlen(filename) + 30);
	snprintf(fn_temp, strlen(filename)+30, "%s.tmp%d", filename, getpid());
	ret = buf_writefile(buf, fn_temp);

	if (ret == DROPBEAR_FAILURE) {
		goto out;
	}

	if (link(fn_temp, filename) < 0) {
		/* If generating keys on connection (skipexist) it's OK to get EEXIST 
		- we probably just lost a race with another connection to generate the key */
		if (!(skip_exist && errno == EEXIST)) {
			dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", filename,
				strerror(errno));
			/* XXX fallback to non-atomic copy for some filesystems? */
			ret = DROPBEAR_FAILURE;
			goto out;
		}
	}

out:
	if (buf) {
		buf_burn(buf);
		buf_free(buf);
	}
	
	if (fn_temp) {
		unlink(fn_temp);
		m_free(fn_temp);
	}

	return ret;
}
Esempio n. 19
0
/* Generate our side of the diffie-hellman key exchange value (dh_f), and
 * calculate the session key using the diffie-hellman algorithm. Following
 * that, the session hash is calculated, and signed with RSA or DSS. The
 * result is sent to the client. 
 *
 * See the ietf-secsh-transport draft, section 6, for details */
static void send_msg_kexdh_reply(mp_int *dh_e) {

	mp_int dh_p, dh_q, dh_g, dh_y, dh_f;
	unsigned char randbuf[DH_P_LEN];
	int dh_q_len;
	hash_state hs;

	TRACE(("enter send_msg_kexdh_reply"));
	
	assert(ses.kexstate.recvkexinit);

	m_mp_init_multi(&dh_g, &dh_p, &dh_q, &dh_y, &dh_f, NULL);

	/* read the prime and generator*/
	if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN)
			!= MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}
	
	if (mp_set_int(&dh_g, dh_g_val) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	/* calculate q = (p-1)/2 */
	if (mp_sub_d(&dh_p, 1, &dh_y) != MP_OKAY) { /*dh_y is just a temp var here*/
		dropbear_exit("Diffie-Hellman error");
	}
	if (mp_div_2(&dh_y, &dh_q) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	dh_q_len = mp_unsigned_bin_size(&dh_q);

	/* calculate our random value dh_y */
	do {
		assert((unsigned int)dh_q_len <= sizeof(randbuf));
		genrandom(randbuf, dh_q_len);
		if (mp_read_unsigned_bin(&dh_y, randbuf, dh_q_len) != MP_OKAY) {
			dropbear_exit("Diffie-Hellman error");
		}
	} while (mp_cmp(&dh_y, &dh_q) == MP_GT || mp_cmp_d(&dh_y, 0) != MP_GT);

	/* f = g^y mod p */
	if (mp_exptmod(&dh_g, &dh_y, &dh_p, &dh_f) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}
	mp_clear(&dh_g);

	/* K = e^y mod p */
	ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int));
	m_mp_init(ses.dh_K);
	if (mp_exptmod(dh_e, &dh_y, &dh_p, ses.dh_K) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	/* clear no longer needed vars */
	mp_clear_multi(&dh_y, &dh_p, &dh_q, NULL);

	/* Create the remainder of the hash buffer, to generate the exchange hash */
	/* K_S, the host key */
	buf_put_pub_key(ses.kexhashbuf, ses.opts->hostkey, 
			ses.newkeys->algo_hostkey);
	/* e, exchange value sent by the client */
	buf_putmpint(ses.kexhashbuf, dh_e);
	/* f, exchange value sent by the server */
	buf_putmpint(ses.kexhashbuf, &dh_f);
	/* K, the shared secret */
	buf_putmpint(ses.kexhashbuf, ses.dh_K);

	/* calculate the hash H to sign */
	sha1_init(&hs);
	buf_setpos(ses.kexhashbuf, 0);
	sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
			ses.kexhashbuf->len);
	sha1_done(&hs, ses.hash);
	buf_free(ses.kexhashbuf);
	ses.kexhashbuf = NULL;
	
	/* first time around, we set the session_id to H */
	if (ses.session_id == NULL) {
		/* create the session_id, this never needs freeing */
		ses.session_id = (unsigned char*)m_malloc(SHA1_HASH_SIZE);
		memcpy(ses.session_id, ses.hash, SHA1_HASH_SIZE);
	}
	
	/* we can start creating the kexdh_reply packet */
	CHECKCLEARTOWRITE();
	buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY);
	buf_put_pub_key(ses.writepayload, ses.opts->hostkey,
			ses.newkeys->algo_hostkey);

	/* put f */
	buf_putmpint(ses.writepayload, &dh_f);
	mp_clear(&dh_f);

	/* calc the signature */
	buf_put_sign(ses.writepayload, ses.opts->hostkey, 
			ses.newkeys->algo_hostkey, ses.hash, SHA1_HASH_SIZE);

	/* the SSH_MSG_KEXDH_REPLY is done */
	encrypt_packet();

	TRACE(("leave send_msg_kexdh_reply"));
}
Esempio n. 20
0
struct rename_node {
	struct rename_node *next;
	char *old;
	char *new;
};

/* Global variables. */
static struct rename_node *rename_head = NULL;

static struct rename_node *
rename_node_new(const char *old, const char *new, struct rename_node *next)
{
	struct rename_node *node;

	node = m_malloc(sizeof(*node));
	node->next = next;
	node->old = m_strdup(old);
	node->new = m_strdup(new);

	return node;
}

static void
rename_node_free(struct rename_node *node)
{
	free(node->old);
	free(node->new);
	free(node);
}
Esempio n. 21
0
enum modstatdb_rw modstatdb_init(const char *adir, enum modstatdb_rw readwritereq) {
  const struct fni *fnip;
  
  admindir= adir;

  for (fnip=fnis; fnip->suffix; fnip++) {
    free(*fnip->store);
    *fnip->store= m_malloc(strlen(adir)+strlen(fnip->suffix)+2);
    sprintf(*fnip->store, "%s/%s", adir, fnip->suffix);
  }

  cflags= readwritereq & msdbrw_flagsmask;
  readwritereq &= ~msdbrw_flagsmask;

  switch (readwritereq) {
  case msdbrw_needsuperuser:
  case msdbrw_needsuperuserlockonly:
    if (getuid() || geteuid())
      ohshit(_("requested operation requires superuser privilege"));
    /* fall through */
  case msdbrw_write: case msdbrw_writeifposs:
    if (access(adir,W_OK)) {
      if (errno != EACCES)
        ohshite(_("unable to access dpkg status area"));
      else if (readwritereq == msdbrw_write)
        ohshit(_("operation requires read/write access to dpkg status area"));
      cstatus= msdbrw_readonly;
    } else {
      lockdatabase(adir);
      cstatus= (readwritereq == msdbrw_needsuperuserlockonly ?
                msdbrw_needsuperuserlockonly :
                msdbrw_write);
    }
    break;
  case msdbrw_readonly:
    cstatus= msdbrw_readonly; break;
  default:
    internerr("unknown modstatdb_rw '%d'", readwritereq);
  }

  updatefnbuf= m_malloc(strlen(adir)+sizeof(UPDATESDIR)+IMPORTANTMAXLEN+5);
  strcpy(updatefnbuf,adir);
  strcat(updatefnbuf,"/" UPDATESDIR);
  updatefnrest= updatefnbuf+strlen(updatefnbuf);

  if (cstatus != msdbrw_needsuperuserlockonly) {
    cleanupdates();
    if(!(cflags & msdbrw_noavail))
    parsedb(availablefile,
            pdb_recordavailable|pdb_rejectstatus,
            NULL,NULL,NULL);
  }

  if (cstatus >= msdbrw_write) {
    createimptmp();
    varbufinit(&uvb, 10240);
  }

  trig_fixup_awaiters(cstatus);
  trig_incorporate(cstatus, admindir);

  return cstatus;
}
Esempio n. 22
0
void process_archive(const char *filename) {
  static const struct TarFunctions tf = {
    tarfileread,
    tarobject, tarobject, tarobject, tarobject, tarobject
  };

  /* These need to be static so that we can pass their addresses to
   * push_cleanup as arguments to the cu_xxx routines; if an error occurs
   * we unwind the stack before processing the cleanup list, and these
   * variables had better still exist ...
   */
  static int p1[2];
  static char cidirtmpnambuf[L_tmpnam+100];
  static char *cidirbuf = NULL, *reasmbuf = NULL;
  static struct fileinlist *newconffiles, *newfileslist;
  static enum pkgstatus oldversionstatus;
  static struct varbuf infofnvb, fnvb, depprobwhy;
  static struct tarcontext tc;
  
  int c1, r, admindirlen, i, infodirlen, infodirbaseused, status;
  struct pkgiterator *it;
  struct pkginfo *pkg, *otherpkg, *divpkg;
  char *cidir, *cidirrest, *p;
  char *pfilenamebuf, conffilenamebuf[MAXCONFFILENAME];
  char *psize;
  const char *pfilename, *newinfofilename;
  struct fileinlist *newconff, **newconffileslastp;
  struct fileinlist *cfile;
  struct reversefilelistiter rlistit;
  struct conffile *searchconff, **iconffileslastp, *newiconff;
  struct filepackages *packageslump;
  struct dependency *dsearch, *newdeplist, **newdeplistlastp;
  struct dependency *newdep, *dep, *providecheck;
  struct deppossi *psearch, **newpossilastp, *possi, *newpossi, *pdep;
  FILE *conff;
  DIR *dsd;
  struct filenamenode *namenode;
  struct dirent *de;
  struct stat stab, oldfs;
  struct pkg_deconf_list *deconpil, *deconpiltemp;
  
  cleanup_pkg_failed= cleanup_conflictor_failed= 0;
  admindirlen= strlen(admindir);

  for (pfilename= filename ; pfilename && strlen(pfilename) > 30 &&
      strchr(pfilename,'/') != NULL ; pfilename++ )
    pfilename= strchr(pfilename,'/');
  if (pfilename && pfilename != filename) {
    pfilenamebuf= (char *)nfmalloc(strlen(pfilename)+5);
    strcpy(pfilenamebuf,".../");
    strcat(pfilenamebuf,pfilename);
    pfilename= pfilenamebuf;
  } else {
    pfilename= filename;
  }

  if (stat(filename,&stab)) ohshite(_("cannot access archive"));

  if (!f_noact) {
    /* We can't `tentatively-reassemble' packages. */
    if (!reasmbuf) {
      reasmbuf= m_malloc(admindirlen+sizeof(REASSEMBLETMP)+5);
      strcpy(reasmbuf,admindir);
      strcat(reasmbuf,"/" REASSEMBLETMP);
    }
    if (unlink(reasmbuf) && errno != ENOENT)
      ohshite(_("error ensuring `%.250s' doesn't exist"),reasmbuf);
    push_cleanup(cu_pathname, ~0, NULL, 0, 1, (void *)reasmbuf);
    c1= m_fork();
    if (!c1) {
      execlp(SPLITTER, SPLITTER, "-Qao", reasmbuf, filename, NULL);
      ohshite(_("failed to exec dpkg-split to see if it's part of a multiparter"));
    }
    while ((r= waitpid(c1,&status,0)) == -1 && errno == EINTR);
    if (r != c1) { onerr_abort++; ohshite(_("wait for dpkg-split failed")); }
    switch (WIFEXITED(status) ? WEXITSTATUS(status) : -1) {
    case 0:
      /* It was a part - is it complete ? */
      if (!stat(reasmbuf,&stab)) { /* Yes. */
        filename= reasmbuf;
        pfilename= _("reassembled package file");
        break;
      } else if (errno == ENOENT) { /* No.  That's it, we skip it. */
        return;
      }
    case 1:
      /* No, it wasn't a part. */
      break;
    default:
      checksubprocerr(status,SPLITTER,0);
    }
  }
  
  /* Verify the package. */
  if (!f_nodebsig && (stat(DEBSIGVERIFY, &stab)==0)) {
    printf(_("Authenticating %s ...\n"), filename);
    fflush(stdout);
    c1 = m_fork();
    if (!c1) {
      execl(DEBSIGVERIFY, DEBSIGVERIFY, "-q", filename, NULL);
      ohshite(_("failed to execl debsig-verify"));
    } else {
      int status;
      waitpid(c1, &status, 0);
      if (!(WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
	if (! fc_badverify) {
	  ohshit(_("Verification on package %s failed!"), filename);
	} else {
	  fprintf(stderr, _("Verification on package %s failed,\nbut installing anyway as you requested.\n"), filename);
	}
      } else {
	printf(_("passed\n"));
      }
    }
  }
    

  if (f_noact) {
    cidir= cidirtmpnambuf;
    /* We use tmpnam here, not to get a unique filename, but to get a unique directory. */
    if (!tmpnam(cidir)) ohshite(_("unable to get unique filename for control info"));
    strcat(cidir,"/");
  } else {
    /* We want it to be on the same filesystem so that we can
     * use rename(2) to install the postinst &c.
     */
    if (!cidirbuf)
      cidirbuf= m_malloc(admindirlen+sizeof(CONTROLDIRTMP)+MAXCONTROLFILENAME+10);
    cidir= cidirbuf;
    strcpy(cidir,admindir);
    strcat(cidir, "/" CONTROLDIRTMP);
  }
  cidirrest= cidir + strlen(cidir);

  assert(*cidir && cidirrest[-1] == '/');
  cidirrest[-1] = '\0';
  ensure_pathname_nonexisting(cidir); cidirrest[-1]= '/';
  
  push_cleanup(cu_cidir, ~0, NULL, 0, 2, (void *)cidir, (void *)cidirrest);
  c1= m_fork();
  if (!c1) {
    cidirrest[-1] = '\0';
    execlp(BACKEND, BACKEND, "--control", filename, cidir, NULL);
    ohshite(_("failed to exec dpkg-deb to extract control information"));
  }
  waitsubproc(c1,BACKEND " --control",0);
  strcpy(cidirrest,CONTROLFILE);

  parsedb(cidir, pdb_recordavailable | pdb_rejectstatus | pdb_ignorefiles,
          &pkg,NULL,NULL);
  if (!pkg->files) {
    pkg->files= nfmalloc(sizeof(struct filedetails));
    pkg->files->next = NULL;
    pkg->files->name = pkg->files->msdosname = pkg->files->md5sum = NULL;
  }
  /* Always nfmalloc.  Otherwise, we may overwrite some other field(like md5sum). */
  psize = nfmalloc(30);
  sprintf(psize, "%lu", (unsigned long)stab.st_size);
  pkg->files->size = psize;

  if (cipaction->arg == act_avail) {
    printf(_("Recorded info about %s from %s.\n"),pkg->name,pfilename);
    pop_cleanup(ehflag_normaltidy);
    return;
  }

  if (pkg->available.architecture && *pkg->available.architecture &&
      strcmp(pkg->available.architecture,"all") &&
      strcmp(pkg->available.architecture,architecture))
    forcibleerr(fc_architecture,
                _("package architecture (%s) does not match system (%s)"),
                pkg->available.architecture,architecture);
    
  if (!pkg->installed.valid) blankpackageperfile(&pkg->installed);
  assert(pkg->available.valid);

  for (deconpil= deconfigure;
       deconpil;
       deconpil= deconpiltemp) {
    deconpiltemp= deconpil->next;
    free(deconpil);
  }
  deconfigure = NULL;
  clear_istobes();

  if (!wanttoinstall(pkg,&pkg->available.version,1)) {
      pop_cleanup(ehflag_normaltidy);
      return;
  }

  /* Check if anything is installed that we conflict with, or not installed
   * that we need */
  pkg->clientdata->istobe= itb_installnew;

  for (dsearch= pkg->available.depends; dsearch; dsearch= dsearch->next) {
    switch (dsearch->type) {
    case dep_conflicts:
      /* Look for things we conflict with. */
      check_conflict(dsearch, pkg, pfilename);
      break;
    case dep_breaks:
      /* Look for things we break. */
      check_breaks(dsearch, pkg, pfilename);
      break;
    case dep_provides:
      /* Look for things that conflict with what we provide. */
      if (dsearch->list->ed->installed.valid) {
        for (psearch= dsearch->list->ed->installed.depended;
             psearch;
             psearch= psearch->nextrev) {
          if (psearch->up->type != dep_conflicts) continue;
          check_conflict(psearch->up, pkg, pfilename);
        }
      }
      break;
    case dep_suggests:
    case dep_recommends:
    case dep_depends:
    case dep_replaces:
    case dep_enhances:
      /* Ignore these here. */
      break;
    case dep_predepends:
      if (!depisok(dsearch, &depprobwhy, NULL, 1)) {
        varbufaddc(&depprobwhy,0);
        fprintf(stderr, _("dpkg: regarding %s containing %s, pre-dependency problem:\n%s"),
                pfilename, pkg->name, depprobwhy.buf);
        if (!force_depends(dsearch->list))
          ohshit(_("pre-dependency problem - not installing %.250s"),pkg->name);
        warning(_("ignoring pre-dependency problem!"));
      }
    }
  }
  /* Look for things that conflict with us. */
  for (psearch= pkg->installed.depended; psearch; psearch= psearch->nextrev) {
    if (psearch->up->type != dep_conflicts) continue;
    check_conflict(psearch->up, pkg, pfilename);
  }
  
  ensure_allinstfiles_available();
  filesdbinit();
  trig_file_interests_ensure();

  if (pkg->status != stat_notinstalled && pkg->status != stat_configfiles) {
    printf(_("Preparing to replace %s %s (using %s) ...\n"),
           pkg->name,
           versiondescribe(&pkg->installed.version,vdew_nonambig),
           pfilename);
    log_action("upgrade", pkg);
  } else {
    printf(_("Unpacking %s (from %s) ...\n"),pkg->name,pfilename);
    log_action("install", pkg);
  }

  if (f_noact) {
    pop_cleanup(ehflag_normaltidy);
    return;
  }

  /*
   * OK, we're going ahead.
   */

  trig_activate_packageprocessing(pkg);
  strcpy(cidirrest, TRIGGERSCIFILE);
  trig_parse_ci(cidir, NULL, trig_cicb_statuschange_activate, pkg);

  /* Read the conffiles, and copy the hashes across. */
  newconffiles = NULL;
  newconffileslastp = &newconffiles;
  push_cleanup(cu_fileslist, ~0, NULL, 0, 0);
  strcpy(cidirrest,CONFFILESFILE);
  conff= fopen(cidir,"r");
  if (conff) {
    push_cleanup(cu_closefile, ehflag_bombout, NULL, 0, 1, (void *)conff);
    while (fgets(conffilenamebuf,MAXCONFFILENAME-2,conff)) {
      p= conffilenamebuf + strlen(conffilenamebuf);
      assert(p != conffilenamebuf);
      if (p[-1] != '\n')
        ohshit(_("name of conffile (starting `%.250s') is too long (>%d characters)"),
               conffilenamebuf, MAXCONFFILENAME);
      while (p > conffilenamebuf && isspace(p[-1])) --p;
      if (p == conffilenamebuf) continue;
      *p = '\0';
      namenode= findnamenode(conffilenamebuf, 0);
      namenode->oldhash= NEWCONFFILEFLAG;
      newconff= newconff_append(&newconffileslastp, namenode);
      
      /* Let's see if any packages have this file.  If they do we
       * check to see if they listed it as a conffile, and if they did
       * we copy the hash across.  Since (for plain file conffiles,
       * which is the only kind we are supposed to have) there will
       * only be one package which `has' the file, this will usually
       * mean we only look in the package which we're installing now.
       * The `conffiles' data in the status file is ignored when a
       * package isn't also listed in the file ownership database as
       * having that file.  If several packages are listed as owning
       * the file we pick one at random.
       */
      searchconff = NULL;
      for (packageslump= newconff->namenode->packages;
           packageslump;
           packageslump= packageslump->more) {
        for (i=0; i < PERFILEPACKAGESLUMP && packageslump->pkgs[i]; i++) {
          otherpkg= packageslump->pkgs[i];
          debug(dbg_conffdetail,"process_archive conffile `%s' in package %s - conff ?",
                newconff->namenode->name,otherpkg->name);
          for (searchconff= otherpkg->installed.conffiles;
               searchconff && strcmp(newconff->namenode->name,searchconff->name);
               searchconff= searchconff->next)
            debug(dbg_conffdetail,
                  "process_archive conffile `%s' in package %s - conff ? not `%s'",
                  newconff->namenode->name,otherpkg->name,searchconff->name);
          if (searchconff) {
            debug(dbg_conff,"process_archive conffile `%s' package=%s %s hash=%s",
                  newconff->namenode->name,otherpkg->name,
                  otherpkg == pkg ? "same" : "different!",
                  searchconff->hash);
            if (otherpkg == pkg) goto xit_conff_hashcopy_srch;
          }
        }
      }
    xit_conff_hashcopy_srch:
      if (searchconff) {
        newconff->namenode->oldhash= searchconff->hash;
	/* we don't copy `obsolete'; it's not obsolete in the new package */
      } else {
        debug(dbg_conff,"process_archive conffile `%s' no package, no hash",
              newconff->namenode->name);
      }
      newconff->namenode->flags |= fnnf_new_conff;
    }
    if (ferror(conff)) ohshite(_("read error in %.250s"),cidir);
    pop_cleanup(ehflag_normaltidy); /* conff= fopen() */
    if (fclose(conff)) ohshite(_("error closing %.250s"),cidir);
  } else {
    if (errno != ENOENT) ohshite(_("error trying to open %.250s"),cidir);
  }

  /* All the old conffiles are marked with a flag, so that we don't delete
   * them if they seem to disappear completely.
   */
  oldconffsetflags(pkg->installed.conffiles);
  for (i = 0 ; i < cflict_index ; i++) {
    oldconffsetflags(conflictor[i]->installed.conffiles);
  }
  
  oldversionstatus= pkg->status;

  assert(oldversionstatus <= stat_installed);
  debug(dbg_general,"process_archive oldversionstatus=%s",
        statusstrings[oldversionstatus]);
  
  if (oldversionstatus == stat_halfconfigured ||
      oldversionstatus == stat_triggersawaited ||
      oldversionstatus == stat_triggerspending ||
      oldversionstatus == stat_installed) {
    pkg->eflag |= eflag_reinstreq;
    pkg->status= stat_halfconfigured;
    modstatdb_note(pkg);
    push_cleanup(cu_prermupgrade, ~ehflag_normaltidy, NULL, 0, 1, (void *)pkg);
    maintainer_script_alternative(pkg, PRERMFILE, "pre-removal", cidir, cidirrest,
                                  "upgrade", "failed-upgrade");
    pkg->status= stat_unpacked;
    oldversionstatus= stat_unpacked;
    modstatdb_note(pkg);
  }

  for (deconpil= deconfigure; deconpil; deconpil= deconpil->next) {
    struct pkginfo *removing = deconpil->pkg_removal;

    if (removing)
      printf(_("De-configuring %s, to allow removal of %s ...\n"),
             deconpil->pkg->name, removing->name);
    else
      printf(_("De-configuring %s ...\n"), deconpil->pkg->name);

    trig_activate_packageprocessing(deconpil->pkg);
    deconpil->pkg->status= stat_halfconfigured;
    modstatdb_note(deconpil->pkg);

    /* This means that we *either* go and run postinst abort-deconfigure,
     * *or* queue the package for later configure processing, depending
     * on which error cleanup route gets taken.
     */
    push_cleanup(cu_prermdeconfigure, ~ehflag_normaltidy,
                 ok_prermdeconfigure, ehflag_normaltidy,
                 3, (void*)deconpil->pkg, (void*)removing, (void*)pkg);

    if (removing) {
      maintainer_script_installed(deconpil->pkg, PRERMFILE, "pre-removal",
                                  "deconfigure", "in-favour", pkg->name,
                                  versiondescribe(&pkg->available.version,
                                                  vdew_nonambig),
                                  "removing", removing->name,
                                  versiondescribe(&removing->installed.version,
                                                  vdew_nonambig),
                                  NULL);
    } else {
      maintainer_script_installed(deconpil->pkg, PRERMFILE, "pre-removal",
                                  "deconfigure", "in-favour", pkg->name,
                                  versiondescribe(&pkg->available.version,
                                                  vdew_nonambig),
                                  NULL);
    }
  }

  for (i = 0 ; i < cflict_index; i++) {
    if (!(conflictor[i]->status == stat_halfconfigured ||
          conflictor[i]->status == stat_triggersawaited ||
          conflictor[i]->status == stat_triggerspending ||
          conflictor[i]->status == stat_installed)) continue;
    trig_activate_packageprocessing(conflictor[i]);
    conflictor[i]->status= stat_halfconfigured;
    modstatdb_note(conflictor[i]);
    push_cleanup(cu_prerminfavour, ~ehflag_normaltidy, NULL, 0,
                 2,(void*)conflictor[i],(void*)pkg);
    maintainer_script_installed(conflictor[i], PRERMFILE, "pre-removal",
                                "remove", "in-favour", pkg->name,
                                versiondescribe(&pkg->available.version,
                                                vdew_nonambig),
                                NULL);
    conflictor[i]->status= stat_halfinstalled;
    modstatdb_note(conflictor[i]);
  }

  pkg->eflag |= eflag_reinstreq;
  if (pkg->status == stat_notinstalled)
    pkg->installed.version= pkg->available.version;
  pkg->status= stat_halfinstalled;
  modstatdb_note(pkg);
  if (oldversionstatus == stat_notinstalled) {
    push_cleanup(cu_preinstverynew, ~ehflag_normaltidy, NULL, 0,
                 3,(void*)pkg,(void*)cidir,(void*)cidirrest);
    maintainer_script_new(pkg, PREINSTFILE, "pre-installation", cidir, cidirrest,
                          "install", NULL);
  } else if (oldversionstatus == stat_configfiles) {
    push_cleanup(cu_preinstnew, ~ehflag_normaltidy, NULL, 0,
                 3,(void*)pkg,(void*)cidir,(void*)cidirrest);
    maintainer_script_new(pkg, PREINSTFILE, "pre-installation", cidir, cidirrest,
                          "install", versiondescribe(&pkg->installed.version,
                                                     vdew_nonambig),
                          NULL);
  } else {
    push_cleanup(cu_preinstupgrade, ~ehflag_normaltidy, NULL, 0,
                 4,(void*)pkg,(void*)cidir,(void*)cidirrest,(void*)&oldversionstatus);
    maintainer_script_new(pkg, PREINSTFILE, "pre-installation", cidir, cidirrest,
                          "upgrade", versiondescribe(&pkg->installed.version,
                                                     vdew_nonambig),
                          NULL);
    printf(_("Unpacking replacement %.250s ...\n"),pkg->name);
  }
  
  /*
   * Now we unpack the archive, backing things up as we go.
   * For each file, we check to see if it already exists.
   * There are several possibilities:
   * + We are trying to install a non-directory ...
   *  - It doesn't exist.  In this case we simply extract it.
   *  - It is a plain file, device, symlink, &c.  We do an `atomic
   *    overwrite' using link() and rename(), but leave a backup copy.
   *    Later, when we delete the backup, we remove it from any other
   *    packages' lists.
   * -  It is a directory.  In this case it depends on whether we're
   *    trying to install a symlink or something else.
   *   = If we're not trying to install a symlink we move the directory
   *     aside and extract the node.  Later, when we recursively remove
   *     the backed-up directory, we remove it from any other packages'
   *     lists.
   *   = If we are trying to install a symlink we do nothing - ie,
   *     dpkg will never replace a directory tree with a symlink.  This
   *     is to avoid embarrassing effects such as replacing a directory
   *     tree with a link to a link to the original directory tree.
   * + We are trying to install a directory ...
   *  - It doesn't exist.  We create it with the appropriate modes.
   *  - It exists as a directory or a symlink to one.  We do nothing.
   *  - It is a plain file or a symlink (other than to a directory).
   *    We move it aside and create the directory.  Later, when we
   *    delete the backup, we remove it from any other packages' lists.
   *
   *                   Install non-dir   Install symlink   Install dir
   *  Exists not               X               X                X
   *  File/node/symlink       LXR             LXR              BXR
   *  Directory               BXR              -                -
   *
   *    X: extract file/node/link/directory
   *   LX: atomic overwrite leaving backup
   *    B: ordinary backup
   *    R: later remove from other packages' lists
   *    -: do nothing
   * 
   * After we've done this we go through the remaining things in the
   * lists of packages we're trying to remove (including the old
   * version of the current package).  This happens in reverse order,
   * so that we process files before the directories (or symlinks-to-
   * directories) containing them.
   * + If the thing is a conffile then we leave it alone for the purge
   *   operation.
   * + Otherwise, there are several possibilities too:
   *  - The listed thing does not exist.  We ignore it.
   *  - The listed thing is a directory or a symlink to a directory.
   *    We delete it only if it isn't listed in any other package.
   *  - The listed thing is not a directory, but was part of the package
   *    that was upgraded, we check to make sure the files aren't the
   *    same ones from the old package by checking dev/inode
   *  - The listed thing is not a directory or a symlink to one (ie,
   *    it's a plain file, device, pipe, &c, or a symlink to one, or a
   *    dangling symlink).  We delete it.
   * The removed packages' list becomes empty (of course, the new
   * version of the package we're installing will have a new list,
   * which replaces the old version's list).
   *
   * If at any stage we remove a file from a package's list, and the
   * package isn't one we're already processing, and the package's
   * list becomes empty as a result, we `vanish' the package.  This
   * means that we run its postrm with the `disappear' argument, and
   * put the package in the `not-installed' state.  If it had any
   * conffiles, their hashes and ownership will have been transferred
   * already, so we just ignore those and forget about them from the
   * point of view of the disappearing package.
   *
   * NOTE THAT THE OLD POSTRM IS RUN AFTER THE NEW PREINST, since the
   * files get replaced `as we go'.
   */

  m_pipe(p1);
  push_cleanup(cu_closepipe, ehflag_bombout, NULL, 0, 1, (void *)&p1[0]);
  c1= m_fork();
  if (!c1) {
    m_dup2(p1[1],1); close(p1[0]); close(p1[1]);
    execlp(BACKEND, BACKEND, "--fsys-tarfile", filename, NULL);
    ohshite(_("unable to exec dpkg-deb to get filesystem archive"));
  }
  close(p1[1]);
  p1[1] = -1;

  newfileslist = NULL;
  tc.newfilesp = &newfileslist;
  push_cleanup(cu_fileslist, ~0, NULL, 0, 0);
  tc.pkg= pkg;
  tc.backendpipe= p1[0];

  r= TarExtractor((void*)&tc, &tf);
  if (r) {
    if (errno) {
      ohshite(_("error reading dpkg-deb tar output"));
    } else {
      ohshit(_("corrupted filesystem tarfile - corrupted package archive"));
    }
  }
  fd_null_copy(p1[0], -1, _("dpkg-deb: zap possible trailing zeros"));
  close(p1[0]);
  p1[0] = -1;
  waitsubproc(c1,BACKEND " --fsys-tarfile",PROCPIPE);

  if (oldversionstatus == stat_halfinstalled || oldversionstatus == stat_unpacked) {
    /* Packages that were in `installed' and `postinstfailed' have been reduced
     * to `unpacked' by now, by the running of the prerm script.
     */
    pkg->status= stat_halfinstalled;
    modstatdb_note(pkg);
    push_cleanup(cu_postrmupgrade, ~ehflag_normaltidy, NULL, 0, 1, (void *)pkg);
    maintainer_script_alternative(pkg, POSTRMFILE, "post-removal", cidir, cidirrest,
                                  "upgrade", "failed-upgrade");
  }

  /* If anything goes wrong while tidying up it's a bit late to do
   * anything about it.  However, we don't install the new status
   * info yet, so that a future dpkg installation will put everything
   * right (we hope).
   *
   * If something does go wrong later the `conflictor' package will be
   * left in the `removal_failed' state.  Removing or installing it
   * will be impossible if it was required because of the conflict with
   * the package we're installing now and (presumably) the dependency
   * by other packages.  This means that the files it contains in
   * common with this package will hang around until we successfully
   * get this package installed, after which point we can trust the
   * conflicting package's file list, which will have been updated to
   * remove any files in this package.
   */
  push_checkpoint(~ehflag_bombout, ehflag_normaltidy);
  
  /* Now we delete all the files that were in the old version of
   * the package only, except (old or new) conffiles, which we leave
   * alone.
   */
  reversefilelist_init(&rlistit,pkg->clientdata->files);
  while ((namenode= reversefilelist_next(&rlistit))) {
    struct filenamenode *usenode;

    if ((namenode->flags & fnnf_new_conff) ||
        (namenode->flags & fnnf_new_inarchive))
      continue;

    usenode = namenodetouse(namenode, pkg);
    trig_file_activate(usenode, pkg);

    fnamevb.used= fnameidlu;
    varbufaddstr(&fnamevb, usenode->name);
    varbufaddc(&fnamevb,0);

    if (!stat(namenode->name,&stab) && S_ISDIR(stab.st_mode)) {
      debug(dbg_eachfiledetail, "process_archive: %s is a directory",
	    namenode->name);
      if (isdirectoryinuse(namenode,pkg)) continue;
    }

    if (lstat(fnamevb.buf, &oldfs)) {
      if (!(errno == ENOENT || errno == ELOOP || errno == ENOTDIR))
	warning(_("could not stat old file '%.250s' so not deleting it: %s"),
	        fnamevb.buf, strerror(errno));
      continue;
    }
    if (S_ISDIR(oldfs.st_mode)) {
      if (rmdir(fnamevb.buf)) {
	warning(_("unable to delete old directory '%.250s': %s"),
	        namenode->name, strerror(errno));
      } else if ((namenode->flags & fnnf_old_conff)) {
	warning(_("old conffile '%.250s' was an empty directory "
	          "(and has now been deleted)"), namenode->name);
      }
    } else {
      /* Ok, it's an old file, but is it really not in the new package?
       * It might be known by a different name because of symlinks.
       *
       * We need to check to make sure, so we stat the file, then compare
       * it to the new list. If we find a dev/inode match, we assume they
       * are the same file, and leave it alone. NOTE: we don't check in
       * other packages for sanity reasons (we don't want to stat _all_
       * the files on the system).
       *
       * We run down the list of _new_ files in this package. This keeps
       * the process a little leaner. We are only worried about new ones
       * since ones that stayed the same don't really apply here.
       */
      struct fileinlist *sameas = NULL;
      static struct stat empty_stat;
      struct varbuf cfilename = VARBUF_INIT;

      /* If we can't stat the old or new file, or it's a directory,
       * we leave it up to the normal code
       */
      debug(dbg_eachfile, "process_archive: checking %s for same files on "
	    "upgrade/downgrade", fnamevb.buf);

      for (cfile= newfileslist; cfile; cfile= cfile->next) {
	if (!cfile->namenode->filestat) {
	  struct stat tmp_stat;

	  varbufreset(&cfilename);
	  varbufaddstr(&cfilename, instdir);
	  varbufaddc(&cfilename, '/');
	  varbufaddstr(&cfilename, cfile->namenode->name);
	  varbufaddc(&cfilename, '\0');

	  if (lstat(cfilename.buf, &tmp_stat) == 0) {
	    cfile->namenode->filestat = nfmalloc(sizeof(struct stat));
	    memcpy(cfile->namenode->filestat, &tmp_stat, sizeof(struct stat));
	  } else {
	    if (!(errno == ENOENT || errno == ELOOP || errno == ENOTDIR))
	      ohshite(_("unable to stat other new file `%.250s'"),
		      cfile->namenode->name);
	    cfile->namenode->filestat = &empty_stat;
	    continue;
	  }
	}
	if (cfile->namenode->filestat == &empty_stat)
	  continue;
	if (oldfs.st_dev == cfile->namenode->filestat->st_dev &&
	    oldfs.st_ino == cfile->namenode->filestat->st_ino) {
	  if (sameas)
	    warning(_("old file '%.250s' is the same as several new files! "
	              "(both '%.250s' and '%.250s')"), fnamevb.buf,
		    sameas->namenode->name, cfile->namenode->name);
	  sameas= cfile;
	  debug(dbg_eachfile, "process_archive: not removing %s,"
		" since it matches %s", fnamevb.buf, cfile->namenode->name);
	}
      }

      varbuffree(&cfilename);

      if ((namenode->flags & fnnf_old_conff)) {
	if (sameas) {
	  if (sameas->namenode->flags & fnnf_new_conff) {
	    if (!strcmp(sameas->namenode->oldhash, NEWCONFFILEFLAG)) {
	      sameas->namenode->oldhash= namenode->oldhash;
	      debug(dbg_eachfile, "process_archive: old conff %s"
		    " is same as new conff %s, copying hash",
		    namenode->name, sameas->namenode->name);
	    } else {
	      debug(dbg_eachfile, "process_archive: old conff %s"
		    " is same as new conff %s but latter already has hash",
		    namenode->name, sameas->namenode->name);
	    }
	  }
	} else {
	  debug(dbg_eachfile, "process_archive: old conff %s"
		" is disappearing", namenode->name);
	  namenode->flags |= fnnf_obs_conff;
	  newconff_append(&newconffileslastp, namenode);
	  addfiletolist(&tc, namenode);
	}
	continue;
      }
      
      if (sameas)
	continue;

      if (secure_unlink_statted(fnamevb.buf, &oldfs)) {
        warning(_("unable to securely remove old file '%.250s': %s"),
                namenode->name, strerror(errno));
      }

    } /* !S_ISDIR */
  }

  /* OK, now we can write the updated files-in-this package list,
   * since we've done away (hopefully) with all the old junk.
   */
  write_filelist_except(pkg,newfileslist,0);

  /* Trigger interests may have changed.
   * Firstly we go through the old list of interests deleting them.
   * Then we go through the new list adding them.
   */
  strcpy(cidirrest, TRIGGERSCIFILE);
  trig_parse_ci(pkgadminfile(pkg, TRIGGERSCIFILE),
                trig_cicb_interest_delete, NULL, pkg);
  trig_parse_ci(cidir, trig_cicb_interest_add, NULL, pkg);
  trig_file_interests_save();

  /* We also install the new maintainer scripts, and any other
   * cruft that may have come along with the package.  First
   * we go through the existing scripts replacing or removing
   * them as appropriate; then we go through the new scripts
   * (any that are left) and install them.
   */
  debug(dbg_general, "process_archive updating info directory");
  varbufreset(&infofnvb);
  varbufaddstr(&infofnvb,admindir);
  varbufaddstr(&infofnvb, "/" INFODIR);
  infodirlen= infofnvb.used;
  varbufaddc(&infofnvb,0);
  dsd= opendir(infofnvb.buf);
  if (!dsd) ohshite(_("cannot read info directory"));
  push_cleanup(cu_closedir, ~0, NULL, 0, 1, (void *)dsd);
  while ((de = readdir(dsd)) != NULL) {
    debug(dbg_veryverbose, "process_archive info file `%s'", de->d_name);
    if (de->d_name[0] == '.') continue; /* ignore dotfiles, including `.' and `..' */
    p= strrchr(de->d_name,'.'); if (!p) continue; /* ignore anything odd */
    if (strlen(pkg->name) != (size_t)(p-de->d_name) ||
        strncmp(de->d_name,pkg->name,p-de->d_name)) continue;
    debug(dbg_stupidlyverbose, "process_archive info this pkg");
    /* Right do we have one ? */
    p++; /* skip past the full stop */
    if (!strcmp(p,LISTFILE)) continue; /* We do the list separately */
    if (strlen(p) > MAXCONTROLFILENAME)
      ohshit(_("old version of package has overly-long info file name starting `%.250s'"),
             de->d_name);
    infofnvb.used= infodirlen;
    varbufaddstr(&infofnvb,de->d_name);
    varbufaddc(&infofnvb,0);
    strcpy(cidirrest,p);
    if (!rename(cidir,infofnvb.buf)) {
      debug(dbg_scripts, "process_archive info installed %s as %s",
            cidir, infofnvb.buf);
    } else if (errno == ENOENT) {
      /* Right, no new version. */
      if (unlink(infofnvb.buf))
        ohshite(_("unable to remove obsolete info file `%.250s'"),infofnvb.buf);
      debug(dbg_scripts, "process_archive info unlinked %s",infofnvb.buf);
    } else {
      ohshite(_("unable to install (supposed) new info file `%.250s'"),cidir);
    }
  }
  pop_cleanup(ehflag_normaltidy); /* closedir */
  
  *cidirrest = '\0'; /* the directory itself */
  dsd= opendir(cidir);
  if (!dsd) ohshite(_("unable to open temp control directory"));
  push_cleanup(cu_closedir, ~0, NULL, 0, 1, (void *)dsd);
  while ((de= readdir(dsd))) {
    if (strchr(de->d_name,'.')) {
      debug(dbg_scripts,"process_archive tmp.ci script/file `%s' contains dot",
            de->d_name);
      continue;
    }
    if (strlen(de->d_name) > MAXCONTROLFILENAME)
      ohshit(_("package contains overly-long control info file name (starting `%.50s')"),
             de->d_name);
    strcpy(cidirrest,de->d_name);
    /* First we check it's not a directory. */
    if (!rmdir(cidir))
      ohshit(_("package control info contained directory `%.250s'"),cidir);
    else if (errno != ENOTDIR)
      ohshite(_("package control info rmdir of `%.250s' didn't say not a dir"),de->d_name);
    if (!strcmp(de->d_name,CONTROLFILE)) {
      debug(dbg_scripts,"process_archive tmp.ci script/file `%s' is control",cidir);
      continue; /* ignore the control file */
    }
    if (!strcmp(de->d_name,LISTFILE)) {
      warning(_("package %s contained list as info file"), pkg->name);
      continue;
    }
    /* Right, install it */
    newinfofilename= pkgadminfile(pkg,de->d_name);
    if (rename(cidir,newinfofilename))
      ohshite(_("unable to install new info file `%.250s' as `%.250s'"),
              cidir,newinfofilename);
    debug(dbg_scripts,"process_archive tmp.ci script/file `%s' installed as `%s'",
          cidir, newinfofilename);
  }
  pop_cleanup(ehflag_normaltidy); /* closedir */

  /* Update the status database.
   * This involves copying each field across from the `available'
   * to the `installed' half of the pkg structure.
   * For some of the fields we have to do a complicated construction
   * operation; for others we can just copy the value.
   * We tackle the fields in the order they appear, so that
   * we don't miss any out :-).
   * At least we don't have to copy any strings that are referred
   * to, because these are never modified and never freed.
   */

  /* The dependencies are the most difficult.  We have to build
   * a whole new forward dependency tree.  At least the reverse
   * links (linking our deppossi's into the reverse chains)
   * can be done by copy_dependency_links.
   */
  newdeplist = NULL;
  newdeplistlastp = &newdeplist;
  for (dep= pkg->available.depends; dep; dep= dep->next) {
    newdep= nfmalloc(sizeof(struct dependency));
    newdep->up= pkg;
    newdep->next = NULL;
    newdep->list = NULL;
    newpossilastp = &newdep->list;
    for (possi= dep->list; possi; possi= possi->next) {
      newpossi= nfmalloc(sizeof(struct deppossi));
      newpossi->up= newdep;
      newpossi->ed= possi->ed;
      newpossi->next = NULL;
      newpossi->nextrev = newpossi->backrev = NULL;
      newpossi->verrel= possi->verrel;
      if (possi->verrel != dvr_none)
        newpossi->version= possi->version;
      else
        blankversion(&newpossi->version);
      newpossi->cyclebreak= 0;
      *newpossilastp= newpossi;
      newpossilastp= &newpossi->next;
    }
    newdep->type= dep->type;
    *newdeplistlastp= newdep;
    newdeplistlastp= &newdep->next;
  }
  /* Right, now we've replicated the forward tree, we
   * get copy_dependency_links to remove all the old dependency
   * structures from the reverse links and add the new dependency
   * structures in instead.  It also copies the new dependency
   * structure pointer for this package into the right field.
   */
  copy_dependency_links(pkg,&pkg->installed.depends,newdeplist,0);

  /* The `depended' pointer in the structure doesn't represent anything
   * that is actually specified by this package - it's there so we
   * can find out what other packages refer to this one.  So,
   * we don't copy it.  We go straight on to copy the text fields.
   */
  pkg->installed.essential= pkg->available.essential;
  pkg->installed.description= pkg->available.description;
  pkg->installed.maintainer= pkg->available.maintainer;
  pkg->installed.source= pkg->available.source;
  pkg->installed.architecture= pkg->available.architecture;
  pkg->installed.installedsize= pkg->available.installedsize;
  pkg->installed.version= pkg->available.version;
  pkg->installed.origin = pkg->available.origin;                               
  pkg->installed.bugs = pkg->available.bugs;                                   

  /* We have to generate our own conffiles structure. */
  pkg->installed.conffiles = NULL;
  iconffileslastp = &pkg->installed.conffiles;
  for (cfile= newconffiles; cfile; cfile= cfile->next) {
    newiconff= nfmalloc(sizeof(struct conffile));
    newiconff->next = NULL;
    newiconff->name= nfstrsave(cfile->namenode->name);
    newiconff->hash= nfstrsave(cfile->namenode->oldhash);
    newiconff->obsolete= !!(cfile->namenode->flags & fnnf_obs_conff);
    *iconffileslastp= newiconff;
    iconffileslastp= &newiconff->next;
  }

  /* We can just copy the arbitrary fields list, because it is
   * never even rearranged. Phew!
   */
  pkg->installed.arbs= pkg->available.arbs;

  /* Check for disappearing packages:
   * We go through all the packages on the system looking for ones
   * whose files are entirely part of the one we've just unpacked
   * (and which actually *have* some files!).
   *
   * Any that we find are removed - we run the postrm with `disappear'
   * as an argument, and remove their info/... files and status info.
   * Conffiles are ignored (the new package had better do something
   * with them !).
   */
  it= iterpkgstart();
  while ((otherpkg = iterpkgnext(it)) != NULL) {
    ensure_package_clientdata(otherpkg);
    if (otherpkg == pkg ||
        otherpkg->status == stat_notinstalled ||
        otherpkg->status == stat_configfiles ||
	otherpkg->clientdata->istobe == itb_remove ||
        !otherpkg->clientdata->files) continue;
    debug(dbg_veryverbose, "process_archive checking disappearance %s",otherpkg->name);
    assert(otherpkg->clientdata->istobe == itb_normal ||
           otherpkg->clientdata->istobe == itb_deconfigure);
    for (cfile= otherpkg->clientdata->files;
         cfile && !strcmp(cfile->namenode->name,"/.");
         cfile= cfile->next);
    if (!cfile) {
      debug(dbg_stupidlyverbose, "process_archive no non-root, no disappear");
      continue;
    }
    for (cfile= otherpkg->clientdata->files;
         cfile && !filesavespackage(cfile,otherpkg,pkg);
         cfile= cfile->next);
    if (cfile) continue;

    /* So dependency things will give right answers ... */
    otherpkg->clientdata->istobe= itb_remove; 
    debug(dbg_veryverbose, "process_archive disappear checking dependencies");
    for (pdep= otherpkg->installed.depended;
         pdep;
         pdep= pdep->nextrev) {
      if (pdep->up->type != dep_depends && pdep->up->type != dep_predepends &&
          pdep->up->type != dep_recommends) continue;
      if (depisok(pdep->up, &depprobwhy, NULL, 0))
        continue;
      varbufaddc(&depprobwhy,0);
      debug(dbg_veryverbose,"process_archive cannot disappear: %s",depprobwhy.buf);
      break;
    }
    if (!pdep) {
      /* If we haven't found a reason not to yet, let's look some more. */
      for (providecheck= otherpkg->installed.depends;
           providecheck;
           providecheck= providecheck->next) {
        if (providecheck->type != dep_provides) continue;
        for (pdep= providecheck->list->ed->installed.depended;
             pdep;
             pdep= pdep->nextrev) {
          if (pdep->up->type != dep_depends && pdep->up->type != dep_predepends &&
              pdep->up->type != dep_recommends)
            continue;
          if (depisok(pdep->up, &depprobwhy, NULL, 0))
            continue;
          varbufaddc(&depprobwhy,0);
          debug(dbg_veryverbose,"process_archive cannot disappear (provides %s): %s",
                providecheck->list->ed->name, depprobwhy.buf);
          goto break_from_both_loops_at_once;
        }
      }
    break_from_both_loops_at_once:;
    }
    otherpkg->clientdata->istobe= itb_normal;
    if (pdep) continue;

    printf(_("(Noting disappearance of %s, which has been completely replaced.)\n"),
           otherpkg->name);
    debug(dbg_general, "process_archive disappearing %s",otherpkg->name);
    /* No, we're disappearing it.  This is the wrong time to go and
     * run maintainer scripts and things, as we can't back out.  But
     * what can we do ?  It has to be run this late.
     */
    trig_activate_packageprocessing(otherpkg);
    maintainer_script_installed(otherpkg, POSTRMFILE,
                                "post-removal script (for disappearance)",
                                "disappear", pkg->name, 
                                versiondescribe(&pkg->available.version,
                                                vdew_nonambig),
                                NULL);

    /* OK, now we delete all the stuff in the `info' directory .. */
    varbufreset(&fnvb);
    varbufaddstr(&fnvb,admindir);
    varbufaddstr(&fnvb,"/" INFODIR);
    infodirbaseused= fnvb.used;
    varbufaddc(&fnvb,0);
    dsd= opendir(fnvb.buf); if (!dsd) ohshite(_("cannot read info directory"));
    push_cleanup(cu_closedir, ~0, NULL, 0, 1, (void *)dsd);

    debug(dbg_general, "process_archive disappear cleaning info directory");
      
    while ((de = readdir(dsd)) != NULL) {
      debug(dbg_veryverbose, "process_archive info file `%s'", de->d_name);
      if (de->d_name[0] == '.') continue;
      p= strrchr(de->d_name,'.'); if (!p) continue;
      if (strlen(otherpkg->name) != (size_t)(p-de->d_name) ||
          strncmp(de->d_name,otherpkg->name,p-de->d_name)) continue;
      debug(dbg_stupidlyverbose, "process_archive info this pkg");
      fnvb.used= infodirbaseused;
      varbufaddstr(&fnvb,de->d_name);
      varbufaddc(&fnvb,0);
      if (unlink(fnvb.buf))
        ohshite(_("unable to delete disappearing control info file `%.250s'"),fnvb.buf);
      debug(dbg_scripts, "process_archive info unlinked %s",fnvb.buf);
    }
    pop_cleanup(ehflag_normaltidy); /* closedir */
    
    otherpkg->status= stat_notinstalled;
    otherpkg->want = want_unknown;
    otherpkg->eflag = eflag_ok;

    blankversion(&otherpkg->configversion);
    blankpackageperfile(&otherpkg->installed);

    otherpkg->clientdata->fileslistvalid= 0;

    modstatdb_note(otherpkg);

  } /* while (otherpkg= ... */
  iterpkgend(it);
  
  /* Delete files from any other packages' lists.
   * We have to do this before we claim this package is in any
   * sane kind of state, as otherwise we might delete by mistake
   * a file that we overwrote, when we remove the package which
   * had the version we overwrote.  To prevent this we make
   * sure that we don't claim this package is OK until we
   * have claimed `ownership' of all its files.
   */
  for (cfile= newfileslist; cfile; cfile= cfile->next) {
    if (!(cfile->namenode->flags & fnnf_elide_other_lists)) continue;
    if (cfile->namenode->divert && cfile->namenode->divert->useinstead) {
      divpkg= cfile->namenode->divert->pkg;
      if (divpkg == pkg) {
        debug(dbg_eachfile,
              "process_archive not overwriting any `%s' (overriding, `%s')",
              cfile->namenode->name, cfile->namenode->divert->useinstead->name);
        continue;
      } else {
        debug(dbg_eachfile,
              "process_archive looking for overwriting `%s' (overridden by %s)",
              cfile->namenode->name, divpkg ? divpkg->name : "<local>");
      }        
    } else {
      divpkg = NULL;
      debug(dbg_eachfile, "process_archive looking for overwriting `%s'",
            cfile->namenode->name);
    }
    for (packageslump= cfile->namenode->packages;
         packageslump;
         packageslump= packageslump->more) {
      for (i=0; i < PERFILEPACKAGESLUMP && packageslump->pkgs[i]; i++) {
        otherpkg= packageslump->pkgs[i];
        debug(dbg_eachfiledetail, "process_archive ... found in %s\n",otherpkg->name);
        /* If !fileslistvalid then it's one of the disappeared packages above
         * and we don't bother with it here, clearly.
         */
        if (otherpkg == pkg || !otherpkg->clientdata->fileslistvalid) continue;
        if (otherpkg == divpkg) {
          debug(dbg_eachfiledetail, "process_archive ... diverted, skipping\n");
          continue;
        }

        /* Found one.  We delete remove the list entry for this file,
         * (and any others in the same package) and then mark the package
         * as requiring a reread.
         */
        write_filelist_except(otherpkg, otherpkg->clientdata->files, 1);
        ensure_package_clientdata(otherpkg);
        debug(dbg_veryverbose, "process_archive overwrote from %s",otherpkg->name);
      }
    }
  }

  /* Right, the package we've unpacked is now in a reasonable state.
   * The only thing that we have left to do with it is remove
   * backup files, and we can leave the user to fix that if and when
   * it happens (we leave the reinstall required flag, of course).
   */
  pkg->status= stat_unpacked;
  modstatdb_note(pkg);
  
  /* Now we delete all the backup files that we made when
   * extracting the archive - except for files listed as conffiles
   * in the new package.
   * This time we count it as an error if something goes wrong.
   *
   * Note that we don't ever delete things that were in the old
   * package as a conffile and don't appear at all in the new.
   * They stay recorded as obsolete conffiles and will eventually
   * (if not taken over by another package) be forgotten.
   */
  for (cfile= newfileslist; cfile; cfile= cfile->next) {
    if (cfile->namenode->flags & fnnf_new_conff) continue;
    fnametmpvb.used= fnameidlu;
    varbufaddstr(&fnametmpvb,namenodetouse(cfile->namenode,pkg)->name);
    varbufaddstr(&fnametmpvb,DPKGTEMPEXT);
    varbufaddc(&fnametmpvb,0);
    ensure_pathname_nonexisting(fnametmpvb.buf);
  }

  /* OK, we're now fully done with the main package.
   * This is quite a nice state, so we don't unwind past here.
   */
  pkg->eflag = eflag_ok;
  modstatdb_note(pkg);
  push_checkpoint(~ehflag_bombout, ehflag_normaltidy);

  /* Only the removal of the conflictor left to do.
   * The files list for the conflictor is still a little inconsistent in-core,
   * as we have not yet updated the filename->packages mappings; however,
   * the package->filenames mapping is 
   */
  for (i = 0 ; i < cflict_index ; i++) {
    /* We need to have the most up-to-date info about which files are what ... */
    ensure_allinstfiles_available();
    removal_bulk(conflictor[i]);
  }

  if (cipaction->arg == act_install) add_to_queue(pkg);
}
Esempio n. 23
0
/* called only at the start of a session, set up initial state */
static void session_init(int sock, runopts *opts, int childpipe,
		struct sockaddr *remoteaddr) {

	struct timeval tv;
	TRACE(("enter session_init"));

	ses.remoteaddr = remoteaddr;

	ses.hostname = getaddrhostname(remoteaddr);

	ses.sock = sock;
	ses.maxfd = sock;

	ses.childpipe = childpipe;

	ses.opts = opts;

	if (gettimeofday(&tv, 0) < 0) {
		dropbear_exit("Error getting time");
	}

	ses.connecttime = tv.tv_sec;
	
	kexinitialise(); /* initialise the kex state */
	authinitialise(); /* initialise auth state */
	chaninitialise(); /* initialise the channel state */

	ses.writepayload = buf_new(MAX_TRANS_PAYLOAD_LEN);
	ses.transseq = 0;

	ses.readbuf = NULL;
	ses.decryptreadbuf = NULL;
	ses.payload = NULL;
	ses.recvseq = 0;

	ses.expecting = SSH_MSG_KEXINIT;
	ses.dataallowed = 0; /* don't send data yet, we'll wait until after kex */
	ses.ignorenext = 0;

	/* set all the algos to none */
	ses.keys = (struct key_context*)m_malloc(sizeof(struct key_context));
	ses.newkeys = NULL;
	ses.keys->recv_algo_crypt = &dropbear_nocipher;
	ses.keys->trans_algo_crypt = &dropbear_nocipher;
	
	ses.keys->recv_algo_mac = &dropbear_nohash;
	ses.keys->trans_algo_mac = &dropbear_nohash;

	ses.keys->algo_kex = -1;
	ses.keys->algo_hostkey = -1;
	ses.keys->recv_algo_comp = DROPBEAR_COMP_NONE;
	ses.keys->trans_algo_comp = DROPBEAR_COMP_NONE;

#ifndef DISABLE_ZLIB
	ses.keys->recv_zstream = NULL;
	ses.keys->trans_zstream = NULL;
#endif

	/* key exchange buffers */
	ses.session_id = NULL;
	ses.kexhashbuf = NULL;
	ses.transkexinit = NULL;
	ses.dh_K = NULL;
	ses.remoteident = NULL;

	sessinitdone = 1;

	TRACE(("leave session_init"));
}
Esempio n. 24
0
File: font.c Progetto: thaigiang/VMS
//=====================================
void generateImage(u8* str,u8 length,u16 imgWidth,u16 imgHeight,IMAGE* strImg)
{
	u8 i = 0;
	u16 x = 0,y = 0;
	EFFECT effect = EFFECT_NONE;
	LEDColor ledColor = LED_COLOR_RED;
	FONT_ID fontID = FONT_ID2;
	TEXT_ALIGN align = ALIGN_LEFT;
	u8 index = 0;
	u16 width = 0,width_temp = 0;
	u16 w[10];
	u16 height = 0;
	IMAGE charImg;

	charImg.data = NULL;
	charImg.imgHeight = 0;
	charImg.imgWidth = 0;
	
	// Check font,color,effect
	strImg->imgWidth = 0;

	// Count length of image which used to display string
	i = 0;
	height = 0;
	index = 0;
	while(i<length)
	{
		if(str[i] == HASHTAG)
		{
			i++;
			if(str[i] == 'n')
			{
				if(width_temp < width)
				{
					width_temp = width;					
				}
				w[index] = width;
				index ++;
				width = 0;
				if(charImg.imgHeight)
					height += charImg.imgHeight;
				else
				{
					getChar(fontID,0,&charImg);
					if(charImg.data == NULL)
						return;
					height += charImg.imgHeight;
					m_free(charImg.data);
				}
			}
			else if(str[i] == 'f')
			{
				i++;
				switch(str[i])
				{
					case '0':
						fontID = FONT_ID1;
						break;
					case '1':
						fontID = FONT_ID2;
						break;
					case '2':
						fontID = FONT_ID3;
						break;
					case '3':
						fontID = FONT_ID4;
						break;
					case '4':
						fontID = FONT_ID5;
						break;
					case '5':
						fontID = FONT_ID6;
						break;
					default:
						break;
				}
			}
			else
				i++;
		}
		else
		{
			getChar(fontID,str[i],&charImg);
			width += charImg.imgWidth;
			m_free(charImg.data);
		}
		i++;
	}
	
	height += charImg.imgHeight;

	w[index] = width;
		
	if(width<width_temp)
		width = width_temp;

	// Generate image from string
	strImg->imgHeight = height;
	/*
	if(width%4 != 0)
		strImg->imgWidth = width + (4 - width%4);
	else
		strImg->imgWidth = width;
	if(imgWidth%4 != 0)
		strImg->imgWidth = imgWidth + (4 - imgWidth%4);
	else
		strImg->imgWidth = imgWidth;
	*/
	strImg->imgWidth = imgWidth;
	strImg->imgLength = (strImg->imgHeight*strImg->imgWidth + 3)/4;
	strImg->data = (u8*)m_malloc(sizeof(u8)*strImg->imgLength);
	if(strImg->data == NULL)
		return;
	memset(strImg->data,0x00,strImg->imgLength);
	x = 0;
	y = 0;
	i = 0;
	index = 0;
	charImg.data = NULL;
	charImg.imgHeight = 0;
	charImg.imgWidth = 0;
	while(i<length)
	{
		if(str[i] == HASHTAG)
		{
			i++;
			switch(str[i])
			{
				case 'a':
					i++;
					if(str[i] == 'r')
					{
						x = strImg->imgWidth - w[index];
						align = ALIGN_RIGHT;
					}
					else if(str[i] == 'c')	
					{
						align = ALIGN_CENTER;
						x = (strImg->imgWidth - w[index])/2;
					}
					else if(str[i] == 'l')
					{
						x = 0;
						align = ALIGN_LEFT;
					}
					break;
				case 'f':
					i++;
					switch(str[i])
					{
						case '0':
							fontID = FONT_ID1;
							break;
						case '1':
							fontID = FONT_ID2;
							break;
						case '2':
							fontID = FONT_ID3;
							break;
						case '3':
							fontID = FONT_ID4;
							break;
						case '4':
							fontID = FONT_ID5;
							break;
						case '5':
							fontID = FONT_ID6;
							break;
						default:
							break;
					}
					break;
				case 'c':
					i++;
					if(str[i] == 'r')
						ledColor = LED_COLOR_RED;
					else if(str[i] == 'g')
						ledColor = LED_COLOR_GREEN;
					else if(str[i] == 'y')
						ledColor = LED_COLOR_YELLOW;
					break;
				case 'e':
					i++;
					if(str[i] == '0')
						effect = EFFECT_NONE;
					if(str[i] == '1')
						effect = EFFECT_TOP_DOWN;
					if(str[i] == '2')
						effect = EFFECT_BOTTOM_UP;
					if(str[i] == '3')
						effect = EFFECT_LEFT_RIGHT;
					if(str[i] == '4')
						effect = EFFECT_RIGHT_LEFT;
					break;
				case 'n':
					if(charImg.imgHeight)
						y += charImg.imgHeight;
					else
					{
						getChar(fontID,0,&charImg);
						y += charImg.imgHeight;
						m_free(charImg.data);
					}					
					index ++;
					switch(align)
					{
						case ALIGN_LEFT:
							x = 0;
							break;
						case ALIGN_CENTER:
							if(w[index]<=strImg->imgWidth)
								x = (strImg->imgWidth - w[index])/2;
							else
								x = 0;
							break;
						case ALIGN_RIGHT:
							if(w[index]<=strImg->imgWidth)
								x = strImg->imgWidth - w[index];
							else
								x = 0;
							break;
						default:
							break;
					}
					break;
				default:
					i++;
					break;
			}
		}
		else
		{
			getChar(fontID,str[i],&charImg);
			if((x<=(strImg->imgWidth - charImg.imgWidth)) && (y<=(strImg->imgHeight - charImg.imgHeight)))
			{
				printChar(x,y,strImg,&charImg,ledColor);
				x += charImg.imgWidth;				
			}
			m_free(charImg.data);
		}
		i++;
	}
	strImg->effectType = effect;
	//m_free(charImg.data);
}
Esempio n. 25
0
static int
mksplit(const char *file_src, const char *prefix, size_t partsize,
        size_t maxpartsize, bool msdos)
{
	int fd_src;
	struct stat st;
	char hash[MD5HASHLEN + 1];
	char *package, *version;
	int nparts, curpart;
	off_t startat;
	char *prefixdir = NULL, *msdos_prefix = NULL;
	struct varbuf file_dst = VARBUF_INIT;
	struct varbuf partmagic = VARBUF_INIT;
	struct varbuf partname = VARBUF_INIT;
	char *partdata;

	fd_src = open(file_src, O_RDONLY);
	if (fd_src < 0)
		ohshite(_("unable to open source file `%.250s'"), file_src);
	if (fstat(fd_src, &st))
		ohshite(_("unable to fstat source file"));
	if (!S_ISREG(st.st_mode))
		ohshit(_("source file `%.250s' not a plain file"), file_src);

	fd_md5(fd_src, hash, -1, "md5hash");
	lseek(fd_src, 0, SEEK_SET);

	/* FIXME: Use libdpkg-deb. */
	package = deb_field(file_src, "Package");
	version = deb_field(file_src, "Version");

	nparts = (st.st_size + partsize - 1) / partsize;

	setvbuf(stdout, NULL, _IONBF, 0);

	printf("Splitting package %s into %d parts: ", package, nparts);

	if (msdos) {
		char *t;

		t = m_strdup(prefix);
		prefixdir = m_strdup(dirname(t));
		free(t);

		t = m_strdup(prefix);
		msdos_prefix = m_strdup(basename(t));
		free(t);

		prefix = clean_msdos_filename(msdos_prefix);
	}

	partdata = m_malloc(partsize);
	curpart = 1;

	for (startat = 0; startat < st.st_size; startat += partsize) {
		int fd_dst;
		ssize_t partrealsize;

		varbufreset(&file_dst);
		/* Generate output filename. */
		if (msdos) {
			struct varbuf refname = VARBUF_INIT;
			int prefix_max;

			varbufprintf(&refname, "%dof%d", curpart, nparts);
			prefix_max = max(8 - strlen(refname.buf), 0);
			varbufprintf(&file_dst, "%s/%.*s%.8s.deb",
			             prefixdir, prefix_max, prefix,
			             refname.buf);
			varbuf_destroy(&refname);
		} else {
			varbufprintf(&file_dst, "%s.%dof%d.deb",
			             prefix, curpart, nparts);
		}

		/* Read data from the original package. */
		partrealsize = read(fd_src, partdata, partsize);
		if (partrealsize < 0)
			ohshite("mksplit: read");

		if ((size_t)partrealsize > maxpartsize) {
			ohshit("Header is too long, making part too long. "
			       "Your package name or version\n"
			       "numbers must be extraordinarily long, "
			       "or something. Giving up.\n");
		}

		/* Split the data. */
		fd_dst = open(file_dst.buf, O_CREAT | O_WRONLY, 0644);
		if (fd_dst < 0)
			ohshite(_("unable to open file '%s'"), file_dst.buf);

		/* Write the ar header. */
		dpkg_ar_put_magic(file_dst.buf, fd_dst);

		/* Write the debian-split part. */
		varbufprintf(&partmagic, "%s\n%s\n%s\n%s\n%zu\n%zu\n%d/%d\n",
		             SPLITVERSION, package, version, hash,
		             st.st_size, partsize, curpart, nparts);
		dpkg_ar_member_put_mem(file_dst.buf, fd_dst, PARTMAGIC,
		                       partmagic.buf, partmagic.used);
		varbufreset(&partmagic);

		/* Write the data part. */
		varbufprintf(&partname, "data.%d", curpart);
		dpkg_ar_member_put_mem(file_dst.buf, fd_dst, partname.buf,
		                       partdata, (size_t)partrealsize);
		varbufreset(&partname);

		close(fd_dst);

		printf("%d ", curpart);

		curpart++;
	}

	varbuf_destroy(&file_dst);
	varbuf_destroy(&partname);
	varbuf_destroy(&partmagic);
	free(partdata);

	free(prefixdir);
	free(msdos_prefix);

	close(fd_src);

	printf("done\n");

	return 0;
}
Esempio n. 26
0
int main(int argc, char *argv[]) {

  int i = 0, j = 0;
  int cnt = 0;
  int target = 0, rsize = 0;
  int tsize = 0;

  /* Error Checking */
  if (argc < 2) {
    printf("Usage: %s [-b or -w] input_file\n", argv[0]);
    exit(1);
  }

  load(argv[argc-1]);


  while(cnt != argc-1){
    if(strcmp(argv[cnt], "-b") == 0){
      fit_flag = BEST_FIT;
    }
    else if(strcmp(argv[cnt], "-w") == 0) {
      fit_flag = WORST_FIT;
    } else if(strcmp(argv[cnt], "-np") == 0) {
      print_flag =0;
    }

    cnt++;
  }

  for(i = 0 ; i < query_cnt ; i++) {

    switch(query_list[i].type) {
      case 'm':
      alloc_list[j] = m_malloc(strlen(query_list[i].val) + 1);
      strcpy(alloc_list[j], query_list[i].val);
      j++;
      break;
      case 'f':
      target = atoi(query_list[i].val);
      m_free(alloc_list[target]);
      break;
      case 'a':
      sscanf(query_list[i].val, "%d %d", &target, &rsize);
      tsize = strlen(alloc_list[target]) + rsize;
      m_realloc(alloc_list[target], tsize);
      break;
      case 'd':
      sscanf(query_list[i].val, "%d %d", &target, &rsize);
      tsize = strlen(alloc_list[target]) - rsize;
      m_realloc(alloc_list[target], tsize);
      *(alloc_list[target] + tsize) = '\0';
      break;
      case 'e':
      alloc_list[j++] = m_malloc(atoi(query_list[i].val));
      break;
    }

    print_block_list();
  }

  return 0;
}
Esempio n. 27
0
int parsedb(const char *filename, enum parsedbflags flags,
            struct pkginfo **donep, FILE *warnto, int *warncount) {
  /* warnto, warncount and donep may be null.
   * If donep is not null only one package's information is expected.
   */
  
  static int fd;
  struct pkginfo newpig, *pigp;
  struct pkginfoperfile *newpifp, *pifp;
  struct arbitraryfield *arp, **larpp;
  struct trigaw *ta;
  int pdone;
  int fieldencountered[array_count(fieldinfos)];
  const struct fieldinfo *fip;
  const struct nickname *nick;
  char *data, *dataptr, *endptr;
  const char *fieldstart, *valuestart;
  char *value= NULL;
  int fieldlen= 0, valuelen= 0;
  int *ip, c;
  struct stat st;
  struct parsedb_state ps;

  ps.filename = filename;
  ps.flags = flags;
  ps.lno = 0;
  ps.warnto = warnto;
  ps.warncount = 0;

  newpifp= (flags & pdb_recordavailable) ? &newpig.available : &newpig.installed;
  fd= open(filename, O_RDONLY);
  if (fd == -1) ohshite(_("failed to open package info file `%.255s' for reading"),filename);

  push_cleanup(cu_closefd, ~ehflag_normaltidy, NULL, 0, 1, &fd);

  if (fstat(fd, &st) == -1)
    ohshite(_("can't stat package info file `%.255s'"),filename);

  if (st.st_size > 0) {
#ifdef USE_MMAP
    dataptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
    if (dataptr == MAP_FAILED)
      ohshite(_("can't mmap package info file `%.255s'"),filename);
#else
    dataptr = m_malloc(st.st_size);

    fd_buf_copy(fd, dataptr, st.st_size, _("copy info file `%.255s'"), filename);
#endif
    data= dataptr;
    endptr = dataptr + st.st_size;
  } else {
    data= dataptr= endptr= NULL;
  }

  pdone= 0;
#define EOF_mmap(dataptr, endptr)	(dataptr >= endptr)
#define getc_mmap(dataptr)		*dataptr++;
#define ungetc_mmap(c, dataptr, data)	dataptr--;

  for (;;) { /* loop per package */
    memset(fieldencountered, 0, sizeof(fieldencountered));
    blankpackage(&newpig);

/* Skip adjacent new lines */
    while(!EOF_mmap(dataptr, endptr)) {
      c= getc_mmap(dataptr); if (c!='\n' && c!=MSDOS_EOF_CHAR ) break;
      ps.lno++;
    }
    if (EOF_mmap(dataptr, endptr)) break;
    for (;;) { /* loop per field */
      fieldstart= dataptr - 1;
      while (!EOF_mmap(dataptr, endptr) && !isspace(c) && c!=':' && c!=MSDOS_EOF_CHAR)
        c= getc_mmap(dataptr);
      fieldlen= dataptr - fieldstart - 1;
      while (!EOF_mmap(dataptr, endptr) && c != '\n' && isspace(c)) c= getc_mmap(dataptr);
      if (EOF_mmap(dataptr, endptr))
        parse_error(&ps, &newpig,
                    _("EOF after field name `%.*s'"), fieldlen, fieldstart);
      if (c == '\n')
        parse_error(&ps, &newpig,
                    _("newline in field name `%.*s'"), fieldlen, fieldstart);
      if (c == MSDOS_EOF_CHAR)
        parse_error(&ps, &newpig,
                    _("MSDOS EOF (^Z) in field name `%.*s'"),
                    fieldlen, fieldstart);
      if (c != ':')
        parse_error(&ps, &newpig,
                    _("field name `%.*s' must be followed by colon"),
                    fieldlen, fieldstart);
/* Skip space after ':' but before value and eol */
      while(!EOF_mmap(dataptr, endptr)) {
        c= getc_mmap(dataptr);
        if (c == '\n' || !isspace(c)) break;
      }
      if (EOF_mmap(dataptr, endptr))
        parse_error(&ps, &newpig,
                    _("EOF before value of field `%.*s' (missing final newline)"),
                 fieldlen,fieldstart);
      if (c == MSDOS_EOF_CHAR)
        parse_error(&ps, &newpig,
                    _("MSDOS EOF char in value of field `%.*s' (missing newline?)"),
                    fieldlen,fieldstart);
      valuestart= dataptr - 1;
      for (;;) {
        if (c == '\n' || c == MSDOS_EOF_CHAR) {
          ps.lno++;
	  if (EOF_mmap(dataptr, endptr)) break;
          c= getc_mmap(dataptr);
/* Found double eol, or start of new field */
          if (EOF_mmap(dataptr, endptr) || c == '\n' || !isspace(c)) break;
          ungetc_mmap(c,dataptr, data);
          c= '\n';
        } else if (EOF_mmap(dataptr, endptr)) {
          parse_error(&ps, &newpig,
                      _("EOF during value of field `%.*s' (missing final newline)"),
                      fieldlen,fieldstart);
        }
        c= getc_mmap(dataptr);
      }
      valuelen= dataptr - valuestart - 1;
/* trim ending space on value */
      while (valuelen && isspace(*(valuestart+valuelen-1)))
 valuelen--;
      for (nick = nicknames;
           nick->nick && (strncasecmp(nick->nick, fieldstart, fieldlen) ||
                          nick->nick[fieldlen] != '\0'); nick++) ;
      if (nick->nick) {
	fieldstart= nick->canon;
	fieldlen= strlen(fieldstart);
      }
      for (fip= fieldinfos, ip= fieldencountered;
           fip->name && strncasecmp(fieldstart,fip->name, fieldlen);
           fip++, ip++);
      if (fip->name) {
        value = m_realloc(value, valuelen + 1);
	memcpy(value,valuestart,valuelen);
        *(value + valuelen) = '\0';
        if ((*ip)++)
          parse_error(&ps, &newpig,
                      _("duplicate value for `%s' field"), fip->name);
        fip->rcall(&newpig, newpifp, &ps, value, fip);
      } else {
        if (fieldlen<2)
          parse_error(&ps, &newpig,
                      _("user-defined field name `%.*s' too short"),
                      fieldlen, fieldstart);
        larpp= &newpifp->arbs;
        while ((arp= *larpp) != NULL) {
          if (!strncasecmp(arp->name,fieldstart,fieldlen))
            parse_error(&ps, &newpig,
                       _("duplicate value for user-defined field `%.*s'"),
                       fieldlen, fieldstart);
          larpp= &arp->next;
        }
        arp= nfmalloc(sizeof(struct arbitraryfield));
        arp->name= nfstrnsave(fieldstart,fieldlen);
        arp->value= nfstrnsave(valuestart,valuelen);
        arp->next= NULL;
        *larpp= arp;
      }
      if (EOF_mmap(dataptr, endptr) || c == '\n' || c == MSDOS_EOF_CHAR) break;
    } /* loop per field */
    if (pdone && donep)
      parse_error(&ps, &newpig,
                  _("several package info entries found, only one allowed"));
    parse_must_have_field(&ps, &newpig, newpig.name, "package name");
    if ((flags & pdb_recordavailable) || newpig.status != stat_notinstalled) {
      parse_ensure_have_field(&ps, &newpig,
                              &newpifp->description, "description");
      parse_ensure_have_field(&ps, &newpig,
                              &newpifp->maintainer, "maintainer");
      if (newpig.status != stat_halfinstalled)
        parse_must_have_field(&ps, &newpig,
                              newpifp->version.version, "version");
    }
    if (flags & pdb_recordavailable)
      parse_ensure_have_field(&ps, &newpig,
                              &newpifp->architecture, "architecture");

    /* Check the Config-Version information:
     * If there is a Config-Version it is definitely to be used, but
     * there shouldn't be one if the package is `installed' (in which case
     * the Version and/or Revision will be copied) or if the package is
     * `not-installed' (in which case there is no Config-Version).
     */
    if (!(flags & pdb_recordavailable)) {
      if (newpig.configversion.version) {
        if (newpig.status == stat_installed || newpig.status == stat_notinstalled)
          parse_error(&ps, &newpig,
                      _("Configured-Version for package with inappropriate Status"));
      } else {
        if (newpig.status == stat_installed) newpig.configversion= newpifp->version;
      }
    }

    if (newpig.trigaw.head &&
        (newpig.status <= stat_configfiles ||
         newpig.status >= stat_triggerspending))
      parse_error(&ps, &newpig,
                  _("package has status %s but triggers are awaited"),
                  statusinfos[newpig.status].name);
    else if (newpig.status == stat_triggersawaited && !newpig.trigaw.head)
      parse_error(&ps, &newpig,
                  _("package has status triggers-awaited but no triggers "
                    "awaited"));

    if (!(newpig.status == stat_triggerspending ||
          newpig.status == stat_triggersawaited) &&
        newpig.trigpend_head)
      parse_error(&ps, &newpig,
                  _("package has status %s but triggers are pending"),
                  statusinfos[newpig.status].name);
    else if (newpig.status == stat_triggerspending && !newpig.trigpend_head)
      parse_error(&ps, &newpig,
                  _("package has status triggers-pending but no triggers "
                    "pending"));

    /* FIXME: There was a bug that could make a not-installed package have
     * conffiles, so we check for them here and remove them (rather than
     * calling it an error, which will do at some point).
     */
    if (!(flags & pdb_recordavailable) &&
        newpig.status == stat_notinstalled &&
        newpifp->conffiles) {
      parse_warn(&ps, &newpig,
                 _("Package which in state not-installed has conffiles, "
                   "forgetting them"));
      newpifp->conffiles= NULL;
    }

    /* XXX: Mark not-installed leftover packages for automatic removal on
     * next database dump. This code can be removed after dpkg 1.16.x, when
     * there's guarantee that no leftover is found on the status file on
     * major distributions. */
    if (!(flags & pdb_recordavailable) &&
        newpig.status == stat_notinstalled &&
        newpig.eflag == eflag_ok &&
        (newpig.want == want_purge ||
         newpig.want == want_deinstall ||
         newpig.want == want_hold)) {
      newpig.want = want_unknown;
    }

    pigp= findpackage(newpig.name);
    pifp= (flags & pdb_recordavailable) ? &pigp->available : &pigp->installed;

    if ((flags & pdb_ignoreolder) &&
	versioncompare(&newpifp->version, &pifp->version) < 0)
      continue;

    /* Copy the priority and section across, but don't overwrite existing
     * values if the pdb_weakclassification flag is set.
     */
    if (newpig.section && *newpig.section &&
        !((flags & pdb_weakclassification) && pigp->section && *pigp->section))
      pigp->section= newpig.section;
    if (newpig.priority != pri_unknown &&
        !((flags & pdb_weakclassification) && pigp->priority != pri_unknown)) {
      pigp->priority= newpig.priority;
      if (newpig.priority == pri_other) pigp->otherpriority= newpig.otherpriority;
    }

    /* Sort out the dependency mess. */
    copy_dependency_links(pigp,&pifp->depends,newpifp->depends,
                          (flags & pdb_recordavailable) ? 1 : 0);
    /* Leave the `depended' pointer alone, we've just gone to such
     * trouble to get it right :-).  The `depends' pointer in
     * pifp was indeed also updated by copy_dependency_links,
     * but since the value was that from newpifp anyway there's
     * no need to copy it back.
     */
    newpifp->depended= pifp->depended;

    /* Copy across data */
    memcpy(pifp,newpifp,sizeof(struct pkginfoperfile));
    if (!(flags & pdb_recordavailable)) {
      pigp->want= newpig.want;
      pigp->eflag= newpig.eflag;
      pigp->status= newpig.status;
      pigp->configversion= newpig.configversion;
      pigp->files= NULL;

      pigp->trigpend_head = newpig.trigpend_head;
      pigp->trigaw = newpig.trigaw;
      for (ta = pigp->trigaw.head; ta; ta = ta->sameaw.next) {
        assert(ta->aw == &newpig);
        ta->aw = pigp;
        /* ->othertrigaw_head is updated by trig_note_aw in *(findpackage())
         * rather than in newpig */
      }

    } else if (!(flags & pdb_ignorefiles)) {
      pigp->files= newpig.files;
    }

    if (donep) *donep= pigp;
    pdone++;
    if (EOF_mmap(dataptr, endptr)) break;
    if (c == '\n')
      ps.lno++;
  }
  if (data != NULL) {
#ifdef USE_MMAP
    munmap(data, st.st_size);
#else
    free(data);
#endif
  }
  free(value);
  pop_cleanup(ehflag_normaltidy);
  if (close(fd)) ohshite(_("failed to close after read: `%.255s'"),filename);
  if (donep && !pdone) ohshit(_("no package information in `%.255s'"),filename);

  if (warncount)
    *warncount = ps.warncount;

  return pdone;
}
Esempio n. 28
0
off_t
buffer_hash(const void *input, void *output, int type, off_t limit)
{
	struct buffer_data data = { .arg.ptr = output, .type = type };
	off_t ret;

	buffer_init(NULL, &data);
	ret = buffer_write(&data, input, limit);
	buffer_done(NULL, &data);

	return ret;
}

off_t
buffer_copy(struct buffer_data *read_data, struct buffer_data *write_data,
            off_t limit, const char *desc)
{
	char *buf, *writebuf;
	int bufsize = 32768;
	long bytesread = 0, byteswritten = 0;
	off_t totalread = 0, totalwritten = 0;

	if ((limit != -1) && (limit < bufsize))
		bufsize = limit;
	if (bufsize == 0)
		return 0;

	buf = m_malloc(bufsize);

	while (bytesread >= 0 && byteswritten >= 0 && bufsize > 0) {
		bytesread = buffer_read(read_data, buf, bufsize);
		if (bytesread < 0) {
			if (errno == EINTR || errno == EAGAIN)
				continue;
			break;
		}
		if (bytesread == 0)
			break;

		totalread += bytesread;
		if (limit != -1) {
			limit -= bytesread;
			if (limit < bufsize)
				bufsize = limit;
		}
		writebuf = buf;
		while (bytesread) {
			byteswritten = buffer_write(write_data, writebuf, bytesread);
			if (byteswritten == -1) {
				if (errno == EINTR || errno == EAGAIN)
					continue;
				break;
			}
			if (byteswritten == 0)
				break;

			bytesread -= byteswritten;
			totalwritten += byteswritten;
			writebuf += byteswritten;
		}
	}

	if (bytesread < 0)
		ohshite(_("failed to read on buffer copy for %s"), desc);
	if (byteswritten < 0)
		ohshite(_("failed in write on buffer copy for %s"), desc);
	if (limit > 0)
		ohshit(_("short read on buffer copy for %s"), desc);

	free(buf);

	return totalread;
}
Esempio n. 29
0
/* read the client's choice of algorithms */
static void read_kex() {

	algo_type * algo;
	unsigned char* str;
	char * erralgo = NULL;

	buf_incrpos(ses.payload, 16); /* start after the cookie */

	ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));

	/* kex_algorithms */
	algo = buf_match_algo(ses.payload, sshkex);
	if (algo == NULL) {
		erralgo = "kex";
		goto error;
	}
	ses.newkeys->algo_kex = algo->val;

	/* server_host_key_algorithms */
	algo = buf_match_algo(ses.payload, sshhostkey);
	if (algo == NULL) {
		erralgo = "hostkey";
		goto error;
	}
	ses.newkeys->algo_hostkey = algo->val;

	/* encryption_algorithms_client_to_server */
	algo = buf_match_algo(ses.payload, sshciphers);
	if (algo == NULL) {
		erralgo = "enc c->s";
		goto error;
	}
	ses.newkeys->recv_algo_crypt = (struct dropbear_cipher*)algo->data;

	/* encryption_algorithms_server_to_client */
	algo = buf_match_algo(ses.payload, sshciphers);
	if (algo == NULL) {
		erralgo = "enc s->c";
		goto error;
	}
	ses.newkeys->trans_algo_crypt = (struct dropbear_cipher*)algo->data;

	/* mac_algorithms_client_to_server */
	algo = buf_match_algo(ses.payload, sshhashes);
	if (algo == NULL) {
		erralgo = "mac c->s";
		goto error;
	}
	ses.newkeys->recv_algo_mac = (struct dropbear_hash*)algo->data;

	/* mac_algorithms_server_to_client */
	algo = buf_match_algo(ses.payload, sshhashes);
	if (algo == NULL) {
		erralgo = "mac s->c";
		goto error;
	}
	ses.newkeys->trans_algo_mac = (struct dropbear_hash*)algo->data;

	/* compression_algorithms_client_to_server */
	algo = buf_match_algo(ses.payload, sshcompress);
	if (algo == NULL) {
		erralgo = "comp c->s";
		goto error;
	}
	ses.newkeys->recv_algo_comp = algo->val;

	/* compression_algorithms_server_to_client */
	algo = buf_match_algo(ses.payload, sshcompress);
	if (algo == NULL) {
		erralgo = "comp s->c";
		goto error;
	}
	ses.newkeys->trans_algo_comp = algo->val;

	/* languages_client_to_server */
	str = buf_getstring(ses.payload, NULL);
	m_free(str);

	/* languages_server_to_client */
	str = buf_getstring(ses.payload, NULL);
	m_free(str);

	/* first_kex_packet_follows */
	if (buf_getbyte(ses.payload)) {
		ses.kexstate.firstfollows = 1;
		/* XXX currently not handled */
	}

	/* reserved for future extensions */
	buf_getint(ses.payload);

	return;

error:
	dropbear_exit("no matching algo %s", erralgo);

}
Esempio n. 30
0
int main(int argc, char *argv[]) 
{
    char cwd[PATH_MAX] = { '\0' };
    char *dir = NULL;
    enum dpkg_tar_options taroption = DPKG_TAR_EXTRACT | DPKG_TAR_NOMTIME;
    int admininfo = 0;
    char *debar = argv[1];
    int arfd = -1;
    struct stat stab;
    char versionbuf[40] = { '\0' };
    ssize_t r;
    off_t ctrllennum, memberlen = 0;
    bool header_done;
    char *infobuf = NULL;
    struct dpkg_error err;
    const char *errstr;
    struct deb_version version;
    int adminmember = -1;
    enum compressor_type decompressor = COMPRESSOR_TYPE_GZIP;
    char nlc;
    int dummy;
    int p1[2], p2[2];
    pid_t c1 = 0, c2, c3;
    int p2_out;

    if (getcwd(cwd, PATH_MAX)) {
        dir = m_malloc(PATH_MAX);
        snprintf(dir, PATH_MAX - 1, "%s/extract", cwd);
    }

    arfd = open(debar, O_RDONLY);
    if (arfd < 0)
        ohshite("failed to read archive %s", debar);
    if (fstat(arfd, &stab))
        ohshite("failed to fstat archive");

    r = read_line(arfd, 
                  versionbuf, 
                  strlen(DPKG_AR_MAGIC), 
                  sizeof(versionbuf) - 1);
    if (r < 0)
        read_fail(r, debar, "archive magic version number");

    if (strcmp(versionbuf, DPKG_AR_MAGIC) == 0) {
        ctrllennum = 0;
        header_done = false;
        for (;;) {
            struct ar_hdr arh;
        
            r = fd_read(arfd, &arh, sizeof(arh));
            if (r != sizeof(arh))
                read_fail(r, debar, "archive member header");

            dpkg_ar_normalize_name(&arh);

            if (dpkg_ar_member_is_illegal(&arh)) {
                ohshit("file '%.250s' is corrupt - bad archive header magic", 
                       debar);
            }

            memberlen = dpkg_ar_member_get_size(debar, &arh);
            if (!header_done) {
                infobuf = NULL;

                if (strncmp(arh.ar_name, DEBMAGIC, sizeof(arh.ar_name)) != 0) {
                    ohshit("file '%.250s' is not a debian binary archive "
                           "(try dpkg-split?)", debar);
                }

                infobuf = m_malloc(memberlen + 1);
                r = fd_read(arfd, infobuf, memberlen + (memberlen & 1));
                if (r != (memberlen + (memberlen & 1)))
                    read_fail(r, debar, "archive information header member");
                infobuf[memberlen] = '\0';

                if (strchr(infobuf, '\n') == NULL)
                    ohshit("archive has no newlines in header");

                errstr = deb_version_parse(&version, infobuf);
                if (errstr)
                    ohshit("archive has invalid format version: %s", errstr);
                if (version.major != 2) {
                    ohshit("archive is format version %d.%d; get a newer dpkg-deb",
                           version.major, version.minor);
                }

                if (infobuf) {
                    free(infobuf);
                    infobuf = NULL;
                }

                header_done = true;
            } else if (arh.ar_name[0] == '_') {
                if (fd_skip(arfd, memberlen + (memberlen & 1), &err) < 0) {
                    ohshit("cannot skip archive member from '%s': %s", 
                           debar, err.str);
                }
            } else {
				if (strncmp(arh.ar_name, ADMINMEMBER, strlen(ADMINMEMBER)) == 0) {
                    const char *extension = arh.ar_name + strlen(ADMINMEMBER);

	                adminmember = 1;
                    decompressor = compressor_find_by_extension(extension);
                    if (decompressor != COMPRESSOR_TYPE_NONE &&
                        decompressor != COMPRESSOR_TYPE_GZIP &&
                        decompressor != COMPRESSOR_TYPE_XZ) {
                        ohshit("ERROR: archive '%s' uses unknown compression "
                               "for member '%.*s', giving up", 
                               debar, (int)sizeof(arh.ar_name), arh.ar_name);
                    }
                } else {
                    if (adminmember != 1) {
                        ohshit("archive '%s' has premature member '%.*s' "
                               "before '%s', giving up",
                               debar, (int)sizeof(arh.ar_name), arh.ar_name, 
                               ADMINMEMBER);
                    }

	                if (strncmp(arh.ar_name, DATAMEMBER, strlen(DATAMEMBER)) == 0) {
	                    const char *extension = arh.ar_name + strlen(DATAMEMBER);

	                    adminmember = 0;
	                    decompressor = compressor_find_by_extension(extension);
                        if (decompressor == COMPRESSOR_TYPE_UNKNOWN) {
                            ohshit("archive '%s' uses unknown "
                                   "compression for member '%.*s', giving up",
                                   debar, (int)sizeof(arh.ar_name), arh.ar_name);
                        }
                    } else {
                        ohshit("archive '%s' has premature member '%.*s' "
                               "before '%s', giving up",
                               debar, (int)sizeof(arh.ar_name), arh.ar_name, DATAMEMBER);
                    }
                }
                if (adminmember == 1) {
                    if (ctrllennum != 0) {
                        ohshit("archive '%.250s' contains two control members, giving up",
                              debar);
                    }
                    ctrllennum = memberlen;
                }
                if (!adminmember != !admininfo) {
                    if (fd_skip(arfd, memberlen + (memberlen & 1), &err) < 0) {
                        ohshit("cannot skip archive member from '%s': %s", 
                               debar, err.str);
                    }
                } else {
                    break;
                }
            }
        }

        if (admininfo >= 2) {
            printf(" new debian package, version %d.%d.\n"
                   " size %jd bytes: control archive=%jd bytes.\n",
                   version.major, version.minor,
                   (intmax_t)stab.st_size, (intmax_t)ctrllennum);
            m_output(stdout, "<standard output>");
        }
    } else if (strncmp(versionbuf, "0.93", 4) == 0) {
        char ctrllenbuf[40] = { '\0' };
        int l;

        l = strlen(versionbuf);

        if (strchr(versionbuf, '\n') == NULL)
            ohshit("archive has no newlines in header");
        errstr = deb_version_parse(&version, versionbuf);
        if (errstr)
            ohshit("archive has invalid format version: %s", errstr);

        r = read_line(arfd, ctrllenbuf, 1, sizeof(ctrllenbuf));
        if (r < 0)
            read_fail(r, debar, "archive control member size");
        if (sscanf(ctrllenbuf, "%jd%c%d", &ctrllennum, &nlc, &dummy) != 2 || 
            nlc != '\n') {
            ohshit("archive has malformatted control member size '%s'", 
                   ctrllenbuf);
        }

        if (admininfo) {
            memberlen = ctrllennum;
        } else {
            memberlen = stab.st_size - ctrllennum - strlen(ctrllenbuf) - l;
            if (fd_skip(arfd, ctrllennum, &err) < 0) {
                ohshit("cannot skip archive control member from '%s': %s", 
                        debar, err.str);
            }
        }

        if (admininfo >= 2) {
            printf(" old debian package, version %d.%d.\n"
                   " size %jd bytes: control archive=%jd, main archive=%jd.\n",
                   version.major, version.minor,
                   (intmax_t)stab.st_size, (intmax_t)ctrllennum,
                   (intmax_t)(stab.st_size - ctrllennum - strlen(ctrllenbuf) - l));
            m_output(stdout, "<standard output>");
        }
    } else {
        if (strncmp(versionbuf, "!<arch>", 7) == 0) {
            notice("file looks like it might be an archive which has been\n"
                   " corrupted by being downloaded in ASCII mode");
        }

        ohshit("'%.255s' is not a debian format archive", debar);
    }

    m_pipe(p1);
    c1 = subproc_fork();
    if (!c1) {
        close(p1[0]);
        if (fd_fd_copy(arfd, p1[1], memberlen, &err) < 0)
            ohshit("cannot copy archive member from '%s' to decompressor pipe: %s",
             debar, err.str);
        if (close(p1[1]))
            ohshite("cannot close decompressor pipe");
        exit(0);
    }
    close(p1[1]);

    if (taroption) {
        m_pipe(p2);
        p2_out = p2[1];
    } else {
        p2_out = 1;
    }

    c2 = subproc_fork();
    if (!c2) {
        if (taroption)
            close(p2[0]);
        decompress_filter(decompressor, p1[0], p2_out,
                          "decompressing archive member");
        exit(0);
    }
    close(p1[0]);
    close(arfd);
    if (taroption) 
        close(p2[1]);

    if (taroption) {
        c3 = subproc_fork();
        if (!c3) {
            struct command cmd;

            command_init(&cmd, TAR, "tar");
            command_add_arg(&cmd, "tar");

            if ((taroption & DPKG_TAR_LIST) && (taroption & DPKG_TAR_EXTRACT))
                command_add_arg(&cmd, "-xv");
            else if (taroption & DPKG_TAR_EXTRACT)
                command_add_arg(&cmd, "-x");
            else if (taroption & DPKG_TAR_LIST)
                command_add_arg(&cmd, "-tv");
            else
                internerr("unknown or missing tar action '%d'", taroption);

        if (taroption & DPKG_TAR_PERMS)
            command_add_arg(&cmd, "-p");
        if (taroption & DPKG_TAR_NOMTIME)
            command_add_arg(&cmd, "-m");

        command_add_arg(&cmd, "-f");
        command_add_arg(&cmd, "-");
        command_add_arg(&cmd, "--warning=no-timestamp");

        m_dup2(p2[0],0);
        close(p2[0]);

        unsetenv("TAR_OPTIONS");

        if (dir) {
            if (chdir(dir)) {
                if (errno != ENOENT)
                    ohshite("failed to chdir to directory");

                if (mkdir(dir, 0777))
                    ohshite("failed to create directory");
                if (chdir(dir))
                    ohshite("failed to chdir to directory after creating it");
                }
            }

            command_exec(&cmd);
        }
        close(p2[0]);
        subproc_reap(c3, "tar", 0);
    }

    subproc_reap(c2, "<decompress>", SUBPROC_NOPIPE);
    if (c1 != -1)
        subproc_reap(c1, "paste", 0);
    if (version.major == 0 && admininfo) {
        while (version.minor && (version.minor % 10) == 0)
            version.minor /= 10;

        if (version.minor ==  931)
            movecontrolfiles(OLDOLDDEBDIR);
        else if (version.minor == 932 || version.minor == 933)
            movecontrolfiles(OLDDEBDIR);
    }

    return 0;
}