Пример #1
0
int proxy_http_negotiate (ProxySocket *p, int change)
{
    if (p->state == PROXY_STATE_NEW) {
	/* we are just beginning the proxy negotiate process,
	 * so we'll send off the initial bits of the request.
	 * for this proxy method, it's just a simple HTTP
	 * request
	 */
	char *buf, dest[512];
	char *username, *password;

	sk_getaddr(p->remote_addr, dest, lenof(dest));

	buf = dupprintf("CONNECT %s:%i HTTP/1.1\r\nHost: %s:%i\r\n",
			dest, p->remote_port, dest, p->remote_port);
	sk_write(p->sub_socket, buf, strlen(buf));
	sfree(buf);

	username = conf_get_str(p->conf, CONF_proxy_username);
	password = conf_get_str(p->conf, CONF_proxy_password);
	if (username[0] || password[0]) {
	    char *buf, *buf2;
	    int i, j, len;
	    buf = dupprintf("%s:%s", username, password);
	    len = strlen(buf);
	    buf2 = snewn(len * 4 / 3 + 100, char);
	    sprintf(buf2, "Proxy-Authorization: Basic ");
	    for (i = 0, j = strlen(buf2); i < len; i += 3, j += 4)
		base64_encode_atom((unsigned char *)(buf+i),
				   (len-i > 3 ? 3 : len-i), buf2+j);
	    strcpy(buf2+j, "\r\n");
	    sk_write(p->sub_socket, buf2, strlen(buf2));
	    sfree(buf);
	    sfree(buf2);
	}
Пример #2
0
static int module_init(void)
{
	auth.nonce_expiry = NONCE_EXPIRY;
	auth.secret = rand_u64();

	conf_get_u32(restund_conf(), "auth_nonce_expiry", &auth.nonce_expiry);

	auth.sharedsecret_length = 0;
	auth.sharedsecret2_length = 0;
    conf_get_str(restund_conf(), "auth_shared", auth.sharedsecret, sizeof(auth.sharedsecret));
    auth.sharedsecret_length = strlen(auth.sharedsecret);
    conf_get_str(restund_conf(), "auth_shared_rollover", auth.sharedsecret2, sizeof(auth.sharedsecret2));
    auth.sharedsecret2_length = strlen(auth.sharedsecret2);
    if (auth.sharedsecret_length > 0 || auth.sharedsecret2_length > 0) {
        restund_debug("auth: module loaded shared secret lengths %d and %d\n", 
                      auth.sharedsecret_length,
                      auth.sharedsecret2_length);
    }

	restund_stun_register_handler(&stun);

	restund_debug("auth: module loaded (nonce_expiry=%us)\n",
		      auth.nonce_expiry);

	return 0;
}
Пример #3
0
static int module_init(void)
{
	struct list *vidcodecl = baresip_vidcodecl();
	char h264enc[64];
	char h264dec[64];

#ifdef USE_X264
	debug("avcodec: x264 build %d\n", X264_BUILD);
#else
	debug("avcodec: using libavcodec H.264 encoder\n");
#endif

#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 10, 0)
	avcodec_init();
#endif

#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
	avcodec_register_all();
#endif

	if (0 == conf_get_str(conf_cur(), "avcodec_h264dec",
			      h264dec, sizeof(h264dec))) {

		info("avcodec: using h264 decoder by name (%s)\n", h264dec);

		avcodec_h264dec = avcodec_find_decoder_by_name(h264dec);
		if (!avcodec_h264dec) {
			warning("avcodec: h264 decoder not found (%s)\n",
				h264dec);
			return ENOENT;
		}
		vidcodec_register(vidcodecl, &h264);
	}
	else {
		if (avcodec_find_decoder(AV_CODEC_ID_H264))
			vidcodec_register(vidcodecl, &h264);
	}

	if (avcodec_find_decoder(AV_CODEC_ID_H263))
		vidcodec_register(vidcodecl, &h263);

	if (avcodec_find_decoder(AV_CODEC_ID_MPEG4))
		vidcodec_register(vidcodecl, &mpg4);

	if (0 == conf_get_str(conf_cur(), "avcodec_h264enc",
			      h264enc, sizeof(h264enc))) {

		info("avcodec: using h264 encoder by name (%s)\n", h264enc);

		avcodec_h264enc = avcodec_find_encoder_by_name(h264enc);
		if (!avcodec_h264enc) {
			warning("avcodec: h264 encoder not found (%s)\n",
				h264enc);
			return ENOENT;
		}
	}

	return 0;
}
Пример #4
0
int
x509_crl_init(void)
{
	/*
	 * XXX I'm not sure if the method to use CRLs in certificate validation
	 * is valid for OpenSSL versions prior to 0.9.7. For now, simply do not
	 * support it.
	 */
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
	char	*dirname;
	dirname = conf_get_str("X509-certificates", "CRL-directory");
	if (!dirname) {
		log_print("x509_crl_init: no CRL-directory");
		return 0;
	}
	if (!x509_read_crls_from_dir(x509_cas, dirname)) {
		LOG_DBG((LOG_MISC, 10,
		    "x509_crl_init: x509_read_crls_from_dir failed"));
		return 0;
	}
#else
	LOG_DBG((LOG_CRYPTO, 10, "x509_crl_init: CRL support only "
	    "with OpenSSL v0.9.7 or later"));
#endif

	return 1;
}
Пример #5
0
void RunConfig( Conf * conf /*Config * cfg*/ ) {

		char b[2048];
		char c[180], *cl;
		int freecl = FALSE;
		BOOL inherit_handles;
		STARTUPINFO si;
		PROCESS_INFORMATION pi;
		HANDLE filemap = NULL;

		char bufpass[256] ;
		strcpy( bufpass, conf_get_str(conf,CONF_password));
		MASKPASS(bufpass);
		    /*
		     * Allocate a file-mapping memory chunk for the
		     * config structure.
		     */
		    SECURITY_ATTRIBUTES sa;
		    void *p;
		    int size;

		    size = conf_serialised_size(conf);

		    sa.nLength = sizeof(sa);
		    sa.lpSecurityDescriptor = NULL;
		    sa.bInheritHandle = TRUE;
		    filemap = CreateFileMapping(INVALID_HANDLE_VALUE,
						&sa,
						PAGE_READWRITE,
						0, size, NULL);
		    if (filemap && filemap != INVALID_HANDLE_VALUE) {
			p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, size);
			if (p) {
			    conf_serialise(conf, p);
			    UnmapViewOfFile(p);
			}
		    }
		    inherit_handles = TRUE;
		    sprintf(c, "putty &%p:%u", filemap, (unsigned)size);
		    cl = c;
		memset(bufpass,0,strlen(bufpass));//MASKPASS(cfg->password);
		    
		GetModuleFileName(NULL, b, sizeof(b) - 1);
		si.cb = sizeof(si);
		si.lpReserved = NULL;
		si.lpDesktop = NULL;
		si.lpTitle = NULL;
		si.dwFlags = 0;
		si.cbReserved2 = 0;
		si.lpReserved2 = NULL;
		CreateProcess(b, cl, NULL, NULL, inherit_handles,
			      NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
                CloseHandle(pi.hProcess);
                CloseHandle(pi.hThread);

		if (filemap)
		    CloseHandle(filemap);
		if (freecl)
		    sfree(cl);
	}
Пример #6
0
void
sa_reinit(void)
{
	struct sa      *sa;
	char           *tag;
	int             i;

	/* For now; only do this if we have the proper tag configured.  */
	tag = conf_get_str("General", "Renegotiate-on-HUP");
	if (!tag)
		return;

	LOG_DBG((LOG_SA, 30, "sa_reinit: renegotiating active connections"));

	/*
	 * Get phase 2 SAs. Soft expire those without active exchanges.  Do
	 * not touch a phase 2 SA where the soft expiration is not set, ie.
	 * the SA is not yet established.
	 */
	for (i = 0; i <= bucket_mask; i++)
		for (sa = LIST_FIRST(&sa_tab[i]); sa; sa = LIST_NEXT(sa, link))
			if (sa->phase == 2)
				if (exchange_lookup_by_name(sa->name,
				    sa->phase) == 0 && sa->soft_death) {
					timer_remove_event(sa->soft_death);
					sa_soft_expire(sa);
				}
}
Пример #7
0
static void process_subneg(Telnet telnet)
{
    unsigned char *b, *p, *q;
    int var, value, n, bsize;
    char *e, *eval, *ekey, *user;

    switch (telnet->sb_opt) {
      case TELOPT_TSPEED:
	if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) {
	    char *logbuf;
	    char *termspeed = conf_get_str(telnet->conf, CONF_termspeed);
	    b = snewn(20 + strlen(termspeed), unsigned char);
	    b[0] = IAC;
	    b[1] = SB;
	    b[2] = TELOPT_TSPEED;
	    b[3] = TELQUAL_IS;
	    strcpy((char *)(b + 4), termspeed);
	    n = 4 + strlen(termspeed);
	    b[n] = IAC;
	    b[n + 1] = SE;
	    telnet->bufsize = sk_write(telnet->s, (char *)b, n + 2);
	    logevent(telnet->frontend, "server:\tSB TSPEED SEND");
	    logbuf = dupprintf("client:\tSB TSPEED IS %s", termspeed);
	    logevent(telnet->frontend, logbuf);
	    sfree(logbuf);
	    sfree(b);
	} else
Пример #8
0
/* Initialize our databases and load our own certificates.  */
int
x509_cert_init(void)
{
	char	*dirname;

	x509_hash_init();

	/* Process CA certificates we will trust.  */
	dirname = conf_get_str("X509-certificates", "CA-directory");
	if (!dirname) {
		log_print("x509_cert_init: no CA-directory");
		return 0;
	}
	/* Free if already initialized.  */
	if (x509_cas)
		X509_STORE_free(x509_cas);

	x509_cas = X509_STORE_new();
	if (!x509_cas) {
		log_print("x509_cert_init: creating new X509_STORE failed");
		return 0;
	}
	if (!x509_read_from_dir(x509_cas, dirname, 0, &n_x509_cas)) {
		log_print("x509_cert_init: x509_read_from_dir failed");
		return 0;
	}
	/* Process client certificates we will accept.  */
	dirname = conf_get_str("X509-certificates", "Cert-directory");
	if (!dirname) {
		log_print("x509_cert_init: no Cert-directory");
		return 0;
	}
	/* Free if already initialized.  */
	if (x509_certs)
		X509_STORE_free(x509_certs);

	x509_certs = X509_STORE_new();
	if (!x509_certs) {
		log_print("x509_cert_init: creating new X509_STORE failed");
		return 0;
	}
	if (!x509_read_from_dir(x509_certs, dirname, 1, NULL)) {
		log_print("x509_cert_init: x509_read_from_dir failed");
		return 0;
	}
	return 1;
}
Пример #9
0
static
int
custom_get_time_format(char *s, size_t max)
{
  char buff[256];

  return copy(s, max, conf_get_str(CONF_FORMAT, buff, sizeof buff, "%R"));
}
Пример #10
0
static
int
custom_get_timezone(char *s, size_t max)
{
  char buff[256];
  conf_get_str(CONF_ZONE, buff, sizeof buff, tz_get());
  tz_set(buff);
  return copy(s, max, tz_get());
}
Пример #11
0
static int module_init(void)
{
	aufilt_register(baresip_aufiltl(), &sndfile);

	conf_get_str(conf_cur(), "snd_path", file_path, sizeof(file_path));

	info("sndfile: saving files in %s\n", file_path);

	return 0;
}
Пример #12
0
int log_writetimestamp( struct LogContext *ctx ) {
// "%m/%d/%Y %H:%M:%S "
	if( strlen(conf_get_str(ctx->conf,CONF_logtimestamp) /*ctx->cfg.logtimestamp*/)==0 )  return 1 ;
	char buf[128] = "" ;

	if( poss( "%f", conf_get_str(ctx->conf,CONF_logtimestamp) /*ctx->cfg.logtimestamp*/ ) ) {
		SYSTEMTIME sysTime ;
		GetLocalTime( &sysTime ) ;
		t_strftime( buf, 127, conf_get_str(ctx->conf,CONF_logtimestamp) /*ctx->cfg.logtimestamp*/, sysTime ) ;
		}
	else {
		time_t temps = time( 0 ) ;
		struct tm tm = * localtime( &temps ) ;
		m_strftime( buf, 127, conf_get_str(ctx->conf,CONF_logtimestamp) /*ctx->cfg.logtimestamp*/, &tm ) ;
		}
	
	fwrite(buf, 1, strlen(buf), ctx->lgfp);
	return 1;
	}
Пример #13
0
void
streamer_dsp_init (void) {
    // load dsp chain from file
    char fname[PATH_MAX];
    snprintf (fname, sizeof (fname), "%s/dspconfig", plug_get_config_dir ());
    dsp_chain = streamer_dsp_chain_load (fname);
    if (!dsp_chain) {
        // first run, let's add resampler
        DB_dsp_t *src = (DB_dsp_t *)plug_get_for_id ("SRC");
        if (src) {
            ddb_dsp_context_t *inst = src->open ();
            inst->enabled = 1;
            src->set_param (inst, 0, "48000"); // samplerate
            src->set_param (inst, 1, "2"); // quality=SINC_FASTEST
            src->set_param (inst, 2, "1"); // auto
            inst->next = dsp_chain;
            dsp_chain = inst;
        }
    }

    eqplug = (DB_dsp_t *)plug_get_for_id ("supereq");
    streamer_dsp_postinit ();

    // load legacy eq settings from pre-0.5
    if (eq && eqplug && conf_find ("eq.", NULL)) {
        eq->enabled = deadbeef->conf_get_int ("eq.enable", 0);
        char s[50];

        // 0.4.4 was writing buggy settings, need to multiply by 2 to compensate
        conf_get_str ("eq.preamp", "0", s, sizeof (s));
        snprintf (s, sizeof (s), "%f", atof(s)*2);
        eqplug->set_param (eq, 0, s);
        for (int i = 0; i < 18; i++) {
            char key[100];
            snprintf (key, sizeof (key), "eq.band%d", i);
            conf_get_str (key, "0", s, sizeof (s));
            snprintf (s, sizeof (s), "%f", atof(s)*2);
            eqplug->set_param (eq, 1+i, s);
        }
        // delete obsolete settings
        conf_remove_items ("eq.");
    }
}
Пример #14
0
void xyz_StartSending(Terminal *term)
{
	OPENFILENAME fn;
	char filenames[32000];
	BOOL res;

	memset(&fn, 0, sizeof(fn));
	memset(filenames, 0, sizeof(filenames));
	fn.lStructSize = sizeof(fn);
	fn.lpstrFile = filenames;
	fn.nMaxFile = sizeof(filenames)-1; // the missing -1 was causing a crash on very long selections
	fn.lpstrTitle = "Select files to upload...";
	fn.Flags = OFN_ALLOWMULTISELECT | OFN_CREATEPROMPT | OFN_ENABLESIZING | OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;

	res = GetOpenFileName(&fn);

	if (res)
	{
		char sz_full_params[32767];
		char *p, *curparams;
		p = filenames;

		curparams = sz_full_params;
		sz_full_params[0] = 0;

		curparams += sprintf(curparams, "%s", conf_get_str(term->conf,CONF_szoptions));

		if (*(p+strlen(filenames)+1)==0) {
			sprintf(curparams, " \"%s\"", filenames);
		} else {
			for (;;) {
				p=p+strlen(p)+1;
				if (*p==0)
					break;
				curparams += sprintf(curparams, " \"%s\\%s\"", filenames, p);
			}
		}
		if (xyz_SpawnProcess(term, conf_get_str(term->conf,CONF_szcommand), sz_full_params) == 0) {
			term->xyz_transfering = 1;
		}
	}
}
Пример #15
0
static void rlogin_startup(Rlogin rlogin, const char *ruser)
{
    char z = 0;
    char *p;

    sk_write(rlogin->s, &z, 1);
    p = conf_get_str(rlogin->conf, CONF_localusername);
    sk_write(rlogin->s, p, strlen(p));
    sk_write(rlogin->s, &z, 1);
    sk_write(rlogin->s, ruser, strlen(ruser));
    sk_write(rlogin->s, &z, 1);
    p = conf_get_str(rlogin->conf, CONF_termtype);
    sk_write(rlogin->s, p, strlen(p));
    sk_write(rlogin->s, "/", 1);
    p = conf_get_str(rlogin->conf, CONF_termspeed);
    sk_write(rlogin->s, p, strspn(p, "0123456789"));
    rlogin->bufsize = sk_write(rlogin->s, &z, 1);

    rlogin->prompt = NULL;
}
Пример #16
0
char *get_remote_username(Conf *conf)
{
    char *username = conf_get_str(conf, CONF_username);
    if (*username) {
	return dupstr(username);
    } else if (conf_get_int(conf, CONF_username_from_env)) {
	/* Use local username. */
	return get_username();     /* might still be NULL */
    } else {
	return NULL;
    }
}
Пример #17
0
static int module_init(void)
{
	static struct restund_db db = {
		.allh  = accounts_getall,
		.cnth  = accounts_count,
		.tlogh = NULL,
	};

	conf_get_str(restund_conf(), "mysql_host", my.host, sizeof(my.host));
	conf_get_str(restund_conf(), "mysql_user", my.user, sizeof(my.user));
	conf_get_str(restund_conf(), "mysql_pass", my.pass, sizeof(my.pass));
	conf_get_str(restund_conf(), "mysql_db",   my.db,   sizeof(my.db));
	conf_get_u32(restund_conf(), "mysql_ser", &my.version);

	if (myconnect()) {
		restund_error("mysql: %s\n", mysql_error(&my.mysql));
	}

	restund_db_set_handler(&db);

	return 0;
}
Пример #18
0
int proxy_socks5_selectchap(Proxy_Socket p)
{
  char *username = conf_get_str(p->conf, CONF_proxy_username);
  char *password = conf_get_str(p->conf, CONF_proxy_password);
  if (username[0] || password[0]) {
    char chapbuf[514];
    int ulen;
    chapbuf[0] = '\x01'; /* Version */
    chapbuf[1] = '\x02'; /* Number of attributes sent */
    chapbuf[2] = '\x11'; /* First attribute - algorithms list */
    chapbuf[3] = '\x01'; /* Only one CHAP algorithm */
    chapbuf[4] = '\x85'; /* ...and it's HMAC-MD5, the core one */
    chapbuf[5] = '\x02'; /* Second attribute - username */

    ulen = strlen(username);
    if (ulen > 255)
      ulen = 255;
    if (ulen < 1)
      ulen = 1;

    chapbuf[6] = ulen;
    memcpy(chapbuf + 7, username, ulen);

    sk_write(p->sub_socket, chapbuf, ulen + 7);
    p->chap_num_attributes = 0;
    p->chap_num_attributes_processed = 0;
    p->chap_current_attribute = -1;
    p->chap_current_datalen = 0;

    p->state = 8;
  } else
    plug_closing(p->plug,
                 "Proxy error: Server chose "
                 "CHAP authentication but we didn't offer it!",
                 PROXY_ERROR_GENERAL,
                 0);
  return 1;
}
Пример #19
0
// Based on PuTTY's settings.c
char * get_remote_username(Conf * conf)
{
  char * username = conf_get_str(conf, CONF_username);
  char * result;
  if (*username)
  {
    result = dupstr(username);
  }
  else
  {
    result = nullptr;
  }
  return result;
}
Пример #20
0
/*
 * Called to set up the serial connection.
 * 
 * Returns an error message, or NULL on success.
 *
 * Also places the canonical host name into `realhost'. It must be
 * freed by the caller.
 */
static const char *serial_init(void *frontend_handle, void **backend_handle,
			       Conf *conf,
			       const char *host, int port, char **realhost,
                               int nodelay, int keepalive)
{
    Serial serial;
    const char *err;
    char *line;

    serial = snew(struct serial_backend_data);
    *backend_handle = serial;

    serial->frontend = frontend_handle;
    serial->finished = FALSE;
    serial->inbufsize = 0;
    bufchain_init(&serial->output_data);

    line = conf_get_str(conf, CONF_serline);
    {
	char *msg = dupprintf("Opening serial device %s", line);
	logevent(serial->frontend, msg);
        sfree(msg);
    }

    serial->fd = open(line, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
    if (serial->fd < 0)
	return "Unable to open serial port";

    cloexec(serial->fd);

    err = serial_configure(serial, conf);
    if (err)
	return err;

    *realhost = dupstr(line);

    if (!serial_by_fd)
	serial_by_fd = newtree234(serial_compare_by_fd);
    add234(serial_by_fd, serial);

    serial_uxsel_setup(serial);

    /*
     * Specials are always available.
     */
    update_specials_menu(serial->frontend);

    return NULL;
}
Пример #21
0
/*
 * Open the log file. Takes care of detecting an already-existing
 * file and asking the user whether they want to append, overwrite
 * or cancel logging.
 */
void logfopen(void *handle)
{
    struct LogContext *ctx = (struct LogContext *)handle;
    struct tm tm;
    FILE *fp;
    int mode;

    /* Prevent repeat calls */
    if (ctx->state != L_CLOSED)
	return;

    if (!ctx->logtype)
	return;

    tm = ltime();

    /* substitute special codes in file name */
    if (ctx->currlogfilename)
        filename_free(ctx->currlogfilename);
    ctx->currlogfilename = 
        xlatlognam(conf_get_filename(ctx->conf, CONF_logfilename),
                   conf_get_str(ctx->conf, CONF_host),
                   conf_get_int(ctx->conf, CONF_port), &tm);
#ifdef PERSOPORT
	test_dir( /*&*/ctx->currlogfilename ) ;
#endif

    fp = f_open(ctx->currlogfilename, "r", FALSE);  /* file already present? */
    if (fp) {
	int logxfovr = conf_get_int(ctx->conf, CONF_logxfovr);
	fclose(fp);
	if (logxfovr != LGXF_ASK) {
	    mode = ((logxfovr == LGXF_OVR) ? 2 : 1);
	} else
	    mode = askappend(ctx->frontend, ctx->currlogfilename,
			     logfopen_callback, ctx);
    } else
	mode = 2;		       /* create == overwrite */

    if (mode < 0)
	ctx->state = L_OPENING;
    else
	logfopen_callback(ctx, mode);  /* open the file */
}
Пример #22
0
static void
daemon_shutdown(void)
{
	/* Perform a (protocol-wise) clean shutdown of the daemon.  */
	struct sa	*sa;

	if (sigtermed == 1) {
		log_print("isakmpd: shutting down...");

		if (delete_sas &&
		    strncmp("no", conf_get_str("General", "Delete-SAs"), 2)) {
			/*
			 * Delete all active SAs.  First IPsec SAs, then
			 * ISAKMPD.  Each DELETE is another (outgoing) message.
			 */
			while ((sa = sa_find(phase2_sa_check, NULL)))
				sa_delete(sa, 1);

			while ((sa = sa_find(phase1_sa_check, NULL)))
				sa_delete(sa, 1);
		}

		/* We only want to do this once. */
		sigtermed++;
	}
	if (transport_prio_sendqs_empty()) {
		/*
		 * When the prioritized transport sendq:s are empty, i.e all
		 * the DELETE notifications have been sent, we can shutdown.
		 */

		log_packet_stop();
		log_print("isakmpd: exit");
		exit(0);
	}
}
Пример #23
0
/*
 * This function can accept a NULL pointer as `addr', in which case
 * it will only check the host name.
 */
int proxy_for_destination(SockAddr addr,
                          const char *hostname,
                          int port,
                          Conf *conf)
{
  int s = 0, e = 0;
  char hostip[64];
  int hostip_len, hostname_len;
  const char *exclude_list;

  /*
   * Special local connections such as Unix-domain sockets
   * unconditionally cannot be proxied, even in proxy-localhost
   * mode. There just isn't any way to ask any known proxy type for
   * them.
   */
  if (addr && sk_address_is_special_local(addr))
    return 0; /* do not proxy */

  /*
   * Check the host name and IP against the hard-coded
   * representations of `localhost'.
   */
  if (!conf_get_int(conf, CONF_even_proxy_localhost) &&
      (sk_hostname_is_local(hostname) || (addr && sk_address_is_local(addr))))
    return 0; /* do not proxy */

  /* we want a string representation of the IP address for comparisons */
  if (addr) {
    sk_getaddr(addr, hostip, 64);
    hostip_len = strlen(hostip);
  } else
    hostip_len = 0; /* placate gcc; shouldn't be required */

  hostname_len = strlen(hostname);

  exclude_list = conf_get_str(conf, CONF_proxy_exclude_list);

  /* now parse the exclude list, and see if either our IP
   * or hostname matches anything in it.
   */

  while (exclude_list[s]) {
    while (exclude_list[s] &&
           (isspace((unsigned char)exclude_list[s]) || exclude_list[s] == ','))
      s++;

    if (!exclude_list[s])
      break;

    e = s;

    while (exclude_list[e] &&
           (isalnum((unsigned char)exclude_list[e]) || exclude_list[e] == '-' ||
            exclude_list[e] == '.' || exclude_list[e] == '*'))
      e++;

    if (exclude_list[s] == '*') {
      /* wildcard at beginning of entry */

      if ((addr && strnicmp(hostip + hostip_len - (e - s - 1),
                            exclude_list + s + 1,
                            e - s - 1) == 0) ||
          strnicmp(hostname + hostname_len - (e - s - 1),
                   exclude_list + s + 1,
                   e - s - 1) == 0)
        return 0; /* IP/hostname range excluded. do not use proxy. */

    } else if (exclude_list[e - 1] == '*') {
      /* wildcard at end of entry */

      if ((addr && strnicmp(hostip, exclude_list + s, e - s - 1) == 0) ||
          strnicmp(hostname, exclude_list + s, e - s - 1) == 0)
        return 0; /* IP/hostname range excluded. do not use proxy. */

    } else {
      /* no wildcard at either end, so let's try an absolute
       * match (ie. a specific IP)
       */

      if (addr && strnicmp(hostip, exclude_list + s, e - s) == 0)
        return 0; /* IP/hostname excluded. do not use proxy. */
      if (strnicmp(hostname, exclude_list + s, e - s) == 0)
        return 0; /* IP/hostname excluded. do not use proxy. */
    }

    s = e;

    /* Make sure we really have reached the next comma or end-of-string */
    while (exclude_list[s] && !isspace((unsigned char)exclude_list[s]) &&
           exclude_list[s] != ',')
      s++;
  }

  /* no matches in the exclude list, so use the proxy */
  return 1;
}
Пример #24
0
static void *thr_monitor(void *p)
{
	cJSON *conf = p;
	char *admin_ip;
	socklen_t addr_len;
	int sd, client, is_admin, val = 1;
	char client_ip[CLIENT_HOST_STR];
	struct sockaddr_in local_addr, client_addr;

	if (conf_get_int("MonitorPort", conf)==-1) {
		mylog(L_WARNING, "MonitorPort not defined, monitor thread not created!");
		pthread_exit(NULL);
	}
	admin_ip = conf_get_str("MonitorAdminIp", conf);
	if (admin_ip == NULL) {
		admin_ip = DEFAULT_ADMIN;
	}

	sd = socket(AF_INET, SOCK_STREAM, 0);
	
	if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))<0) {
		mylog(L_ERR, "Can't set SO_REUSEADDR to admin_socket.");
		close(sd);
		abort();
	} 

	local_addr.sin_family = AF_INET;
	local_addr.sin_port = htons((uint16_t)conf_get_int("MonitorPort", conf));
	inet_pton(AF_INET, "0.0.0.0", &local_addr.sin_addr);
	if (bind(sd, &local_addr, sizeof(local_addr))<0) {
		mylog(L_ERR, "Monitor bind failed: %m");
		close(sd);
		abort();
	}

	if (listen(sd, 1)<0) {
		mylog(L_ERR, "Monitor listen failed: %m");
		close(sd);
		abort();
	}

	while (1) {
		client = accept(sd, NULL, NULL);
		if (client < 0) {
			mylog(L_WARNING, "Monitor accept failed: %m");
			continue;
		}

		is_admin = 0;

		addr_len = sizeof(struct sockaddr);
		getpeername(client, (struct sockaddr *)&client_addr, &addr_len);
		inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, (socklen_t)CLIENT_HOST_STR);
		if (!strcmp(client_ip, admin_ip) || !strcmp(client_ip, DEFAULT_ADMIN)) {
			is_admin = 1;
		}

		monitor_process(client, conf, is_admin);
	
		//result = cJSON_CreateObject();
		//cJSON_fdPrint(client, result);
		//cJSON_Delete(result);
		//close(client);
	}
}
Пример #25
0
int proxy_socks5_handlechap(Proxy_Socket p)
{

  /* CHAP authentication reply format:
   *  version number (1 bytes) = 1
   *  number of commands (1 byte)
   *
   * For each command:
   *  command identifier (1 byte)
   *  data length (1 byte)
   */
  unsigned char data[260];
  unsigned char outbuf[20];

  while (p->chap_num_attributes == 0 ||
         p->chap_num_attributes_processed < p->chap_num_attributes) {
    if (p->chap_num_attributes == 0 || p->chap_current_attribute == -1) {
      /* CHAP normally reads in two bytes, either at the
       * beginning or for each attribute/value pair.  But if
       * we're waiting for the value's data, we might not want
       * to read 2 bytes.
       */

      if (bufchain_size(&p->pending_input_data) < 2)
        return 1; /* not got anything yet */

      /* get the response */
      bufchain_fetch(&p->pending_input_data, data, 2);
      bufchain_consume(&p->pending_input_data, 2);
    }

    if (p->chap_num_attributes == 0) {
      /* If there are no attributes, this is our first msg
       * with the server, where we negotiate version and
       * number of attributes
       */
      if (data[0] != 0x01) {
        plug_closing(p->plug,
                     "Proxy error: SOCKS proxy wants"
                     " a different CHAP version",
                     PROXY_ERROR_GENERAL,
                     0);
        return 1;
      }
      if (data[1] == 0x00) {
        plug_closing(p->plug,
                     "Proxy error: SOCKS proxy won't"
                     " negotiate CHAP with us",
                     PROXY_ERROR_GENERAL,
                     0);
        return 1;
      }
      p->chap_num_attributes = data[1];
    } else {
      if (p->chap_current_attribute == -1) {
        /* We have to read in each attribute/value pair -
         * those we don't understand can be ignored, but
         * there are a few we'll need to handle.
         */
        p->chap_current_attribute = data[0];
        p->chap_current_datalen = data[1];
      }
      if (bufchain_size(&p->pending_input_data) < p->chap_current_datalen)
        return 1; /* not got everything yet */

      /* get the response */
      bufchain_fetch(&p->pending_input_data, data, p->chap_current_datalen);

      bufchain_consume(&p->pending_input_data, p->chap_current_datalen);

      switch (p->chap_current_attribute) {
      case 0x00:
        /* Successful authentication */
        if (data[0] == 0x00)
          p->state = 2;
        else {
          plug_closing(p->plug,
                       "Proxy error: SOCKS proxy"
                       " refused CHAP authentication",
                       PROXY_ERROR_GENERAL,
                       0);
          return 1;
        }
        break;
      case 0x03:
        outbuf[0] = 0x01; /* Version */
        outbuf[1] = 0x01; /* One attribute */
        outbuf[2] = 0x04; /* Response */
        outbuf[3] = 0x10; /* Length */
        hmacmd5_chap(data,
                     p->chap_current_datalen,
                     conf_get_str(p->conf, CONF_proxy_password),
                     &outbuf[4]);
        sk_write(p->sub_socket, (char *)outbuf, 20);
        break;
      case 0x11:
        /* Chose a protocol */
        if (data[0] != 0x85) {
          plug_closing(p->plug,
                       "Proxy error: Server chose "
                       "CHAP of other than HMAC-MD5 but we "
                       "didn't offer it!",
                       PROXY_ERROR_GENERAL,
                       0);
          return 1;
        }
        break;
      }
      p->chap_current_attribute = -1;
      p->chap_num_attributes_processed++;
    }
    if (p->state == 8 &&
        p->chap_num_attributes_processed >= p->chap_num_attributes) {
      p->chap_num_attributes = 0;
      p->chap_num_attributes_processed = 0;
      p->chap_current_datalen = 0;
    }
  }
  return 0;
}
Пример #26
0
int
x509_cert_validate(void *scert)
{
	X509_STORE_CTX	csc;
	X509_NAME	*issuer, *subject;
	X509		*cert = (X509 *) scert;
	EVP_PKEY	*key;
	int		res, err;

	/*
	 * Validate the peer certificate by checking with the CA certificates
	 * we trust.
	 */
	X509_STORE_CTX_init(&csc, x509_cas, cert, NULL);
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
	/* XXX See comment in x509_read_crls_from_dir.  */
	if (x509_cas->param->flags & X509_V_FLAG_CRL_CHECK) {
		X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK);
		X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK_ALL);
	}
#elif OPENSSL_VERSION_NUMBER >= 0x00907000L
	/* XXX See comment in x509_read_crls_from_dir.  */
	if (x509_cas->flags & X509_V_FLAG_CRL_CHECK) {
		X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK);
		X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK_ALL);
	}
#endif
	res = X509_verify_cert(&csc);
	err = csc.error;
	X509_STORE_CTX_cleanup(&csc);

	/*
	 * Return if validation succeeded or self-signed certs are not
	 * accepted.
	 *
	 * XXX X509_verify_cert seems to return -1 if the validation should be
	 * retried somehow.  We take this as an error and give up.
	 */
	if (res > 0)
		return 1;
	else if (res < 0 ||
	    (res == 0 && err != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)) {
		if (err)
			log_print("x509_cert_validate: %.100s",
			    X509_verify_cert_error_string(err));
		return 0;
	} else if (!conf_get_str("X509-certificates", "Accept-self-signed")) {
		if (err)
			log_print("x509_cert_validate: %.100s",
			    X509_verify_cert_error_string(err));
		return 0;
	}
	issuer = X509_get_issuer_name(cert);
	subject = X509_get_subject_name(cert);

	if (!issuer || !subject || X509_name_cmp(issuer, subject))
		return 0;

	key = X509_get_pubkey(cert);
	if (!key) {
		log_print("x509_cert_validate: could not get public key from "
		    "self-signed cert");
		return 0;
	}
	if (X509_verify(cert, key) == -1) {
		log_print("x509_cert_validate: self-signed cert is bad");
		return 0;
	}
	return 1;
}
Пример #27
0
static int xyz_SpawnProcess(Terminal *term, const char *incommand, const char *inparams)
{
	STARTUPINFO si;
	SECURITY_ATTRIBUTES sa;
	SECURITY_DESCRIPTOR sd;               //security information for pipes
	
	HANDLE read_stdout, read_stderr, write_stdin, newstdin, newstdout, newstderr; //pipe handles

	
	
	
	term->xyz_Internals = (struct zModemInternals *)smalloc(sizeof(struct zModemInternals));
	memset(term->xyz_Internals, 0, sizeof(struct zModemInternals));

	if (IsWinNT())        //initialize security descriptor (Windows NT)
	{
		InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
		SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
		sa.lpSecurityDescriptor = &sd;
	}
	else sa.lpSecurityDescriptor = NULL;
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.bInheritHandle = TRUE;         //allow inheritable handles
	
	if (!CreatePipe(&newstdin,&write_stdin,&sa,PIPE_SIZE))   //create stdin pipe
	{
		return 1;
	}
	if (!CreatePipe(&read_stdout,&newstdout,&sa,PIPE_SIZE))  //create stdout pipe
	{
		CloseHandle(newstdin);
		CloseHandle(write_stdin);
		return 1;
	}
	if (!CreatePipe(&read_stderr,&newstderr,&sa,PIPE_SIZE))  //create stdout pipe
	{
		CloseHandle(newstdin);
		CloseHandle(write_stdin);
		CloseHandle(newstdout);
		CloseHandle(read_stdout);
		return 1;
	}

	
	GetStartupInfo(&si);      //set startupinfo for the spawned process
				  /*
				  The dwFlags member tells CreateProcess how to make the process.
				  STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW
				  validates the wShowWindow member.
	*/
	si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_HIDE;
	si.hStdOutput = newstdout;
	si.hStdError = newstderr;     //set the new handles for the child process
	si.hStdInput = newstdin;

	
	//system
	if (!DuplicateHandle(GetCurrentProcess(), read_stdout, GetCurrentProcess(), &term->xyz_Internals->read_stdout, 0, FALSE, DUPLICATE_SAME_ACCESS))
	{
		CloseHandle(newstdin);
		CloseHandle(write_stdin);
		CloseHandle(newstdout);
		CloseHandle(read_stdout);
		CloseHandle(newstderr);
		CloseHandle(read_stderr);
		return 1;
	}

	CloseHandle(read_stdout);

	if (!DuplicateHandle(GetCurrentProcess(), read_stderr, GetCurrentProcess(), &term->xyz_Internals->read_stderr, 0, FALSE, DUPLICATE_SAME_ACCESS))
	{
		CloseHandle(newstdin);
		CloseHandle(newstdout);
		CloseHandle(read_stdout);
		CloseHandle(write_stdin);
		CloseHandle(newstderr);
		CloseHandle(read_stderr);
		return 1;
	}

	CloseHandle(read_stderr);

	if (!DuplicateHandle(GetCurrentProcess(), write_stdin, GetCurrentProcess(), &term->xyz_Internals->write_stdin, 0, FALSE, DUPLICATE_SAME_ACCESS))
	{
		CloseHandle(newstdin);
		CloseHandle(write_stdin);
		CloseHandle(newstdout);
		CloseHandle(term->xyz_Internals->read_stdout);
		CloseHandle(newstderr);
		CloseHandle(term->xyz_Internals->read_stderr);
		return 1;
	}

	CloseHandle(write_stdin);
	
	//spawn the child process
	{
		char params[1204];
		const char *p;

		p = incommand + strlen(incommand);
		while (p != incommand) {
			if (*p == '\\' || *p == ' ') { // no space in name either
				p++;
				break;
			}
			p--;
		}
		sprintf(params, "%s %s", p, inparams);

		if (!CreateProcess(incommand,params,NULL, NULL,TRUE,CREATE_NEW_CONSOLE, NULL,conf_get_str(term->conf,CONF_zdownloaddir),&si,&term->xyz_Internals->pi))
		{
			DWORD err = GetLastError();
	//		ErrorMessage("CreateProcess");
			CloseHandle(newstdin);
			CloseHandle(term->xyz_Internals->write_stdin);
			CloseHandle(newstdout);
			CloseHandle(term->xyz_Internals->read_stdout);
			CloseHandle(newstderr);
			CloseHandle(term->xyz_Internals->read_stderr);
			return 1;
		}
	}

	CloseHandle(newstdin);
	CloseHandle(newstdout);
	CloseHandle(newstderr);

	return 0;
}
Пример #28
0
static const char *
cygterm_init(void *frontend_handle, void **backend_handle,
             Conf *conf,
             char *unused_host, int unused_port,
             char **realhost, int nodelay, int keepalive)
{
	/* XXX: I'm not sure if it is OK to overload Plug like this.
	 * cygterm_accepting should only be used for the listening socket
	 * (local->a) while the cygterm_closing, cygterm_receive, and cygterm_sent
	 * should be used only for the actual connection (local->s).
	 */
	static const struct plug_function_table fn_table = {
		cygterm_log,
		cygterm_closing,
		cygterm_receive,
		cygterm_sent,
		cygterm_accepting
	};
	Local local;
	const char *command;
	char cmdline[2 * MAX_PATH];
	int cport;
	const char *err;
	int cmdlinelen;

	cygterm_debug("top");

	local = snew(struct cygterm_backend_data);
	local->fn = &fn_table;
	local->a = NULL;
	local->s = NULL;
	local->conf = conf;
	local->editing = 0;
	local->echoing = 0;
	local->exitcode = 0;
	*backend_handle = local;

	local->frontend = frontend_handle;

	/* set up listen socket for communication with child */
	cygterm_debug("setupCygTerm");

	/* let sk use INADDR_LOOPBACK and let WinSock choose a port */
	local->a = sk_newlistener(0, 0, (Plug)local, 1, ADDRTYPE_IPV4);
	if ((err = sk_socket_error(local->a)) != NULL)
		goto fail_free;

	/* now, get the port that WinSock chose */
	/* XXX: Is there another function in PuTTY to do this? */
	cygterm_debug("getting port");
	cport = sk_getport(local->a);
	if (cport == -1) {
		err = "Failed to get port number for cthelper";
		goto fail_close;
	}

	if (strchr(conf_get_str(local->conf, CONF_termtype), ' ')) {
		err = "term type contains spaces";
		goto fail_close;
	}

	/*  Build cthelper command line */
	if(conf_get_int(conf, CONF_cygterm64)) {
		cmdlinelen = sprintf(cmdline, CTHELPER64" %u %s ", cport, conf_get_str(local->conf, CONF_termtype));
	}
	else {
		cmdlinelen = sprintf(cmdline, CTHELPER" %u %s ", cport, conf_get_str(local->conf, CONF_termtype));
	}
	cmdlinelen += makeAttributes(cmdline + cmdlinelen, conf);

	command = conf_get_str(conf, CONF_cygcmd);
	cygterm_debug("command is :%s:", command);
	/*  A command of  "."  or  "-"  tells us to pass no command arguments to
	 *  cthelper which will then run the user's shell under Cygwin.  */
	if ((command[0]=='-'||command[0]=='.') && command[1]=='\0')
		;
	else if (cmdlinelen + strlen(command) + 2 > sizeof cmdline) {
		err = "command is too long";
		goto fail_close;
	}
	else {
		cmdlinelen += sprintf(cmdline + cmdlinelen, " %s", command);
	}

	/* Add the Cygwin /bin path to the PATH. */
	if (conf_get_int(conf, CONF_cygautopath)) {
		char *cygwinBinPath = getCygwinBin(conf_get_int(conf, CONF_cygterm64));
		if (!cygwinBinPath) {
			/* we'll try anyway */
			cygterm_debug("cygwin bin directory not found");
		}
		else {
			cygterm_debug("found cygwin directory: %s", cygwinBinPath);
			appendPath(cygwinBinPath);
			sfree(cygwinBinPath);
		}
	}

	cygterm_debug("starting cthelper: %s", cmdline);
	if ((err = spawnChild(cmdline, &local->pi, &local->ctl)))
		goto fail_close;

	/*  This should be set to the local hostname, Apparently, realhost is used
	 *  only to set the window title.
	 */
	strcpy(*realhost = smalloc(sizeof CYGTERM_NAME), CYGTERM_NAME);
	cygterm_debug("OK");
	return 0;

fail_close:
	sk_close(local->a);
fail_free:
	sfree(local);
	return err;
}
Пример #29
0
void xyz_ReceiveInit(Terminal *term)
{
	if (xyz_SpawnProcess(term, conf_get_str(term->conf,CONF_rzcommand), conf_get_str(term->conf,CONF_rzoptions)) == 0) {
		term->xyz_transfering = 1;
	}
}
Пример #30
0
Socket new_connection(SockAddr addr,
                      const char *hostname,
                      int port,
                      int privport,
                      int oobinline,
                      int nodelay,
                      int keepalive,
                      Plug plug,
                      Conf *conf)
{
  static const struct socket_function_table socket_fn_table = {
      sk_proxy_plug,
      sk_proxy_close,
      sk_proxy_write,
      sk_proxy_write_oob,
      sk_proxy_write_eof,
      sk_proxy_flush,
      sk_proxy_set_frozen,
      sk_proxy_socket_error,
      NULL, /* peer_info */
  };

  static const struct plug_function_table plug_fn_table = {
      plug_proxy_log,
      plug_proxy_closing,
      plug_proxy_receive,
      plug_proxy_sent,
      plug_proxy_accepting};

  if (conf_get_int(conf, CONF_proxy_type) != PROXY_NONE &&
      proxy_for_destination(addr, hostname, port, conf)) {
    Proxy_Socket ret;
    Proxy_Plug pplug;
    SockAddr proxy_addr;
    char *proxy_canonical_name;
    const char *proxy_type;
    Socket sret;
    int type;

    if ((sret = platform_new_connection(addr,
                                        hostname,
                                        port,
                                        privport,
                                        oobinline,
                                        nodelay,
                                        keepalive,
                                        plug,
                                        conf)) != NULL)
      return sret;

    ret = snew(struct Socket_proxy_tag);
    ret->fn = &socket_fn_table;
    ret->conf = conf_copy(conf);
    ret->plug = plug;
    ret->remote_addr = addr; /* will need to be freed on close */
    ret->remote_port = port;

    ret->error = NULL;
    ret->pending_flush = 0;
    ret->pending_eof = 0;
    ret->freeze = 0;

    bufchain_init(&ret->pending_input_data);
    bufchain_init(&ret->pending_output_data);
    bufchain_init(&ret->pending_oob_output_data);

    ret->sub_socket = NULL;
    ret->state = PROXY_STATE_NEW;
    ret->negotiate = NULL;

    type = conf_get_int(conf, CONF_proxy_type);
    if (type == PROXY_HTTP) {
      ret->negotiate = proxy_http_negotiate;
      proxy_type = "HTTP";
    } else if (type == PROXY_SOCKS4) {
      ret->negotiate = proxy_socks4_negotiate;
      proxy_type = "SOCKS 4";
    } else if (type == PROXY_SOCKS5) {
      ret->negotiate = proxy_socks5_negotiate;
      proxy_type = "SOCKS 5";
    } else if (type == PROXY_TELNET) {
      ret->negotiate = proxy_telnet_negotiate;
      proxy_type = "Telnet";
    } else {
      ret->error = "Proxy error: Unknown proxy method";
      return (Socket)ret;
    }

    {
      char *logmsg = dupprintf("Will use %s proxy at %s:%d to connect"
                               " to %s:%d",
                               proxy_type,
                               conf_get_str(conf, CONF_proxy_host),
                               conf_get_int(conf, CONF_proxy_port),
                               hostname,
                               port);
      plug_log(plug, 2, NULL, 0, logmsg, 0);
      sfree(logmsg);
    }

    /* create the proxy plug to map calls from the actual
     * socket into our proxy socket layer */
    pplug = snew(struct Plug_proxy_tag);
    pplug->fn = &plug_fn_table;
    pplug->proxy_socket = ret;

    {
      char *logmsg = dns_log_msg(conf_get_str(conf, CONF_proxy_host),
                                 conf_get_int(conf, CONF_addressfamily),
                                 "proxy");
      plug_log(plug, 2, NULL, 0, logmsg, 0);
      sfree(logmsg);
    }

    /* look-up proxy */
    proxy_addr = sk_namelookup(conf_get_str(conf, CONF_proxy_host),
                               &proxy_canonical_name,
                               conf_get_int(conf, CONF_addressfamily));
    if (sk_addr_error(proxy_addr) != NULL) {
      ret->error = "Proxy error: Unable to resolve proxy host name";
      sfree(pplug);
      sk_addr_free(proxy_addr);
      return (Socket)ret;
    }
    sfree(proxy_canonical_name);

    {
      char addrbuf[256], *logmsg;
      sk_getaddr(proxy_addr, addrbuf, lenof(addrbuf));
      logmsg = dupprintf("Connecting to %s proxy at %s port %d",
                         proxy_type,
                         addrbuf,
                         conf_get_int(conf, CONF_proxy_port));
      plug_log(plug, 2, NULL, 0, logmsg, 0);
      sfree(logmsg);
    }

    /* create the actual socket we will be using,
     * connected to our proxy server and port.
     */
    ret->sub_socket = sk_new(proxy_addr,
                             conf_get_int(conf, CONF_proxy_port),
                             privport,
                             oobinline,
                             nodelay,
                             keepalive,
                             (Plug)pplug);
    if (sk_socket_error(ret->sub_socket) != NULL)
      return (Socket)ret;

    /* start the proxy negotiation process... */
    sk_set_frozen(ret->sub_socket, 0);
    ret->negotiate(ret, PROXY_CHANGE_NEW);

    return (Socket)ret;
  }