Beispiel #1
0
void
init_database (const char *host, const char *user, const char *pass, const char *data)
{
	MYSQL *d;

	last_host = host;
	last_user = user;
	last_pass = pass;
	last_data = data;

	Db = mysql_init (Db);
	if (!Db) {
		hxd_log("mysql_init() failed: %s", mysql_error(Db));
		return;
	}

	d = mysql_real_connect(Db, host, user, pass, data, 0, 0, 0); 
	if (!d) {
		hxd_log("mysql_real_connect() failed: %s", mysql_error(Db));
		Db = 0;
		return;
	}

	Db = d; 
}
Beispiel #2
0
static RETSIGTYPE
sig_hup (int sig __attribute__((__unused__)))
{
   hxd_log("\n");
   hxd_log("caught SIGHUP");
   timer_add_secs(0, read_config_file, (void *)1);
}
Beispiel #3
0
static RETSIGTYPE
sig_log_info (int sig)
{
   extern const char * const sys_siglist[];
   hxd_log("------");
   hxd_log("caught signal %d", sig);
   hxd_log("%s", sys_siglist[sig]);
}
Beispiel #4
0
void
rcv_file_list (struct htlc_conn *htlc)
{
	char rlpath[MAXPATHLEN], path[MAXPATHLEN];
	int err;

	if (htlc->in.pos == SIZEOF_HL_HDR) {
		hxd_scandir(htlc, ROOTDIR);
		return;
	}
	dh_start(htlc)
		if (dh_type != HTLC_DATA_DIR)
			return;
		if ((err = hldir_to_path(dh, ROOTDIR, rlpath, path))) {
			snd_strerror(htlc, err);
			return;
		}
		if (check_dropbox(htlc, path)) {
			/* snd_strerror(htlc, EPERM); */
			hlwrite(htlc, HTLS_HDR_TASK, 0, 0);
			return;
		}
		if (log_list)
			hxd_log("%s:%s:%u - list %s", htlc->name, htlc->login, htlc->uid, path);
		hxd_scandir(htlc, rlpath);
	dh_end()
}
Beispiel #5
0
static int
read_config_file (void *ptr)
{
   if (ptr)
      hxd_log("SIGHUP: rereading config file");

   hxd_read_config(hxdconf, &hxd_cfg);
   umask(hxd_cfg.permissions.umask);
#if defined(CONFIG_HOTLINE_SERVER)
   read_banlist();
   read_applevolume();
   if (hxd_cfg.operation.hfs)
      hfs_set_config(hxd_cfg.files.fork, hxd_cfg.permissions.files,
            hxd_cfg.permissions.directories, hxd_cfg.files.comment,
            hxd_cfg.files.dir_comment);
#ifdef CONFIG_CIPHER
   cipher_init();
#endif
#ifdef CONFIG_NETWORK
   g_my_sid = hxd_cfg.network.server_id;
#endif
#endif
#if defined(CONFIG_TRACKER_SERVER)
   tracker_read_banlist();
#endif
#ifndef ONLY_TRACKER
   if (hxd_cfg.operation.trxreg)
      tracker_register_init();
#endif

   return 0;
}
Beispiel #6
0
static void log_backtrace(void)
{
   void *frame_ptrs[64];
   int count = backtrace(frame_ptrs, 64);
   char **fnames = backtrace_symbols(frame_ptrs, count);
   int i;
   for (i = 0; i < count; i++)
      hxd_log("%s", fnames[i]);
   free(fnames);
}
Beispiel #7
0
static RETSIGTYPE
sig_fatal (int sig)
{
   sig_log_info(sig);
#ifdef ENABLE_BACKTRACE
   hxd_log("Attempting backtrace...");
   log_backtrace();
#endif
   _exit(sig);
}
Beispiel #8
0
void
sql_query (const char *fmt, ...)
{
	va_list ap;
	char buf[16384];

	if (Db) {
		va_start(ap, fmt);
		vsnprintf(buf, sizeof(buf), fmt, ap);
		va_end(ap);
		if (mysql_query(Db, buf) != 0) {
			// try to re-connect and retry
			init_database(last_host, last_user, last_pass, last_data);
			if (mysql_query(Db, buf) != 0) {
				hxd_log("mysql_query() failed: %s", mysql_error(Db));
				hxd_log("mysql_query() query was: %s", buf);
			}
		}
	}
}
Beispiel #9
0
int
tfn (struct timeval *tv)
{
   struct timeval *ctv;
   time_t s, us, secdiff, usecdiff;

   hxd_log("timer: %u, %u", tv->tv_sec, tv->tv_usec);
   if (tv==&tv1)ctv=&ctv1;else if (tv==&tv2)ctv=&ctv2;else if (tv==&tv3)ctv=&ctv3;
   s = ctv->tv_sec;
   us = ctv->tv_usec;
   gettimeofday(ctv,0);
   secdiff = ctv->tv_sec - s;
   if (us > ctv->tv_usec) {
      secdiff--;
      usecdiff = 1000000 - (us - ctv->tv_usec);
   } else {
      usecdiff = ctv->tv_usec - us;
   }
   hxd_log("real: %u, %u",secdiff,usecdiff);
   return 1;
}
Beispiel #10
0
u_int16_t
insert_into_queue (struct htlc_conn *htlc)
{
	if (nr_queued
	    || (nr_gets > hxd_cfg.limits.total_downloads)
	    || (htlc->nr_gets > htlc->get_limit)) {
		hxd_log("Inserting into queue at #%d. nr_gets=%d, limit=%d, queue limit=%d",
			nr_queued+1, nr_gets, hxd_cfg.limits.total_downloads, hxd_cfg.limits.queue_size);
		nr_queued++;
		return nr_queued;
	} else {
		return 0;
	}
}
Beispiel #11
0
void
rcv_file_mkdir (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0;
	char dir[MAXPATHLEN], filename[NAME_MAX], newbuf[MAXPATHLEN];
	int err;

	dir[0] = 0;

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				err = hldir_to_path(dh, ROOTDIR, dir, dir);
				if (err && err != ENOENT) {
					snd_strerror(htlc, err);
					return;
				}
				break;
		}
	dh_end()

	if (!fnlen && !dir[0]) {
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}
	if (dir[0]) {
		if (fnlen)
			snprintf(newbuf, sizeof(newbuf), "%s/%s", dir, filename);
		else
			strcpy(newbuf, dir);
	} else {
		snprintf(newbuf, sizeof(newbuf), "%s/%s", ROOTDIR, filename);
	}
	if (check_dropbox(htlc, newbuf)) {
		snd_strerror(htlc, EPERM);
		return;
	}

	if (log_mkdir)
		hxd_log("%s:%s:%u - mkdir %s", htlc->name, htlc->login, htlc->uid, newbuf);

	if (SYS_mkdir(newbuf, hxd_cfg.permissions.directories))
		snd_strerror(htlc, errno);
	else
		hlwrite(htlc, HTLS_HDR_TASK, 0, 0);
}
Beispiel #12
0
static void
loopZ (void)
{
   fd_set rfds, wfds;
   struct timeval before, tv;

   gettimeofday(&tv, 0);
   for (;;) {
      register int n, i;

      if (timer_list) {
         gettimeofday(&before, 0);
         timer_check(&tv, &before);
         if (timer_list)
            tv = timer_list->tv;
      }
      rfds = hxd_rfds;
      wfds = hxd_wfds;
      n = select(high_fd + 1, &rfds, &wfds, 0, timer_list ? &tv : 0);
      if (n < 0 && errno != EINTR) {
         hxd_log("loopZ: select: %s", strerror(errno));
         exit(1);
      }
      gettimeofday(&tv, 0);
      if (hxd_cfg.operation.nospam)
         loopZ_timeval = tv;
      if (timer_list) {
         timer_check(&before, &tv);
      }
      if (n <= 0)
         continue;
      for (i = 0; i < high_fd + 1; i++) {
         if (FD_ISSET(i, &rfds) && FD_ISSET(i, &hxd_rfds)) {
            if (hxd_files[i].ready_read)
               hxd_files[i].ready_read(i);
            if (!--n)
               break;
         }
         if (FD_ISSET(i, &wfds) && FD_ISSET(i, &hxd_wfds)) {
            if (hxd_files[i].ready_write)
               hxd_files[i].ready_write(i);
            if (!--n)
               break;
         }
      }
   }
}
Beispiel #13
0
static inline void
fh_sort (struct hl_filelist_hdr **fhdrs, u_int16_t count)
{
#if WANT_TO_TIME_SORT
	static int use_qsort = 1;
	struct timeval start, now;
	double diff;
	char secsbuf[32];

	if (use_qsort) {
		gettimeofday(&start, 0);
		qsort(fhdrs, count, sizeof(struct hl_filelist_hdr *), fh_compare);
		gettimeofday(&now, 0);
	} else {
		u_int16_t i, j;
		struct hl_filelist_hdr *fhp;

		gettimeofday(&start, 0);
		for (i = 0; i < count; i++)
			for (j = 1; j < count - i; j++)
				if (fhdrs[j - 1]->fname[0] > fhdrs[j]->fname[0]) {
					fhp = fhdrs[j - 1];
					fhdrs[j - 1] = fhdrs[j];
					fhdrs[j] = fhp;
				}
		gettimeofday(&now, 0);
	}
	diff = (double)(now.tv_sec + now.tv_usec * 0.000001)
	     - (double)(start.tv_sec + start.tv_usec * 0.000001);
	sprintf(secsbuf, "%g", diff);
	hxd_log("%ssort %u took %s seconds", use_qsort ? "q" : "bubble ", count, secsbuf);
	use_qsort = !use_qsort;
#else
	qsort(fhdrs, count, sizeof(struct hl_filelist_hdr *), fh_compare);
#endif
}
Beispiel #14
0
static void
account_getdirs (const char *login, char *rootdir, char *newsfile, char *dropbox)
{
   struct stat sb;
   char dir[MAXPATHLEN];

   if (snprintf(dir, MAXPATHLEN, "%s/%s/files", hxd_cfg.paths.accounts, login) == -1) {
      hxd_log("account_getdirs(%s): path '%s' too long?!?", login, dir);
      goto default_files;
   }

#ifdef HAVE_CORESERVICES
   if (!resolve_alias_path(dir, rootdir) || stat(rootdir, &sb)) {
#else
   if (!realpath(dir, rootdir) || stat(rootdir, &sb)) {
#endif
default_files:
#ifdef HAVE_CORESERVICES
      if (!resolve_alias_path(hxd_cfg.paths.files, rootdir)) {
#else
      if (!realpath(hxd_cfg.paths.files, rootdir)) {
#endif
         hxd_log("could not get realpath of files dir '%s'", hxd_cfg.paths.files);
         snprintf(rootdir, MAXPATHLEN, "%s", hxd_cfg.paths.files);
      }
   }

   if (snprintf(dir, MAXPATHLEN, "%s/%s/news", hxd_cfg.paths.accounts, login) == -1) {
      hxd_log("account_getdirs(%s): path '%s' too long?!?", login, dir);
      goto default_news;
   }

#ifdef HAVE_CORESERVICES
   if (!resolve_alias_path(dir, newsfile) || stat(newsfile, &sb)) {
#else
   if (!realpath(dir, newsfile) || stat(newsfile, &sb)) {
#endif
default_news:
#ifdef HAVE_CORESERVICES
      if (!resolve_alias_path(hxd_cfg.paths.news, newsfile)) {
#else
      if (!realpath(hxd_cfg.paths.news, newsfile)) {
#endif
         hxd_log("could not get realpath of news file '%s'", hxd_cfg.paths.news);
         snprintf(newsfile, MAXPATHLEN, "%s", hxd_cfg.paths.news);
      }
   }

   if (snprintf(dir, MAXPATHLEN, "%s/%s/dropbox", hxd_cfg.paths.accounts, login) == -1) {
      hxd_log("account_getdirs(%s): path '%s' too long?!?", login, dir);
      goto default_dropbox;
   }

#ifdef HAVE_CORESERVICES
   if (!resolve_alias_path(dir, dropbox) || stat(dropbox, &sb)) {
#else
   if (!realpath(dir, dropbox) || stat(dropbox, &sb)) {
#endif
default_dropbox:
      dropbox[0] = 0;
   }
}

void
account_getconf (struct htlc_conn *htlc)
{
   struct hxd_config cfg;
   char file[MAXPATHLEN];

   account_getdirs(htlc->login, htlc->rootdir, htlc->newsfile, htlc->dropbox);

   if (snprintf(file, MAXPATHLEN, "%s/%s/conf", hxd_cfg.paths.accounts, htlc->login) == -1) {
      hxd_log("account_getconf(%s): path '%s' too long?!?", htlc->login, file);
      return;
   }
   memset(&cfg, 0, sizeof(cfg));
   cfg.limits.individual_exec = hxd_cfg.limits.individual_exec;
   cfg.limits.individual_downloads = hxd_cfg.limits.individual_downloads;
   cfg.limits.individual_uploads = hxd_cfg.limits.individual_uploads;
   cfg.limits.out_Bps = hxd_cfg.limits.out_Bps;
   /* remote server queueing spec */
   cfg.limits.can_omit_queue = hxd_cfg.limits.can_omit_queue;
   hxd_read_config(file, &cfg);
   htlc->get_limit = cfg.limits.individual_downloads > HTXF_GET_MAX ? HTXF_GET_MAX : cfg.limits.individual_downloads;
   htlc->put_limit = cfg.limits.individual_uploads > HTXF_PUT_MAX  ? HTXF_PUT_MAX : cfg.limits.individual_uploads;
   htlc->limit_out_Bps = cfg.limits.out_Bps;
   htlc->exec_limit = cfg.limits.individual_exec;
   /* remote server queuing spec */
   htlc->can_download = cfg.limits.can_omit_queue;
}

int
access_extra_set (struct extra_access_bits *acc, char *p, int val)
{
   switch (p[0]) {
   case 'a':
      if (!strcmp(p, "access_volatile"))
         { acc->access_volatile = val; return 0; }
   case 'c':
      if (!strcmp(p, "can_spam"))
         { acc->can_spam = val; return 0; }
      else if (!strcmp(p, "chat_private"))
         { acc->chat_private = val; return 0; }
   case 'd':
      if (!strcmp(p, "debug"))
         { acc->debug = val; return 0; }
   case 'f':
      if (!strcmp(p, "file_getinfo"))
         { acc->file_getinfo = val; return 0; }
      else if (!strcmp(p, "file_hash"))
         { acc->file_hash = val; return 0; }
      else if (!strcmp(p, "file_list"))
         { acc->file_list = val; return 0; }
   case 'i':
      if (!strcmp(p, "is_0wn3d"))
         { acc->is_0wn3d = val; return 0; }
      else if (!strcmp(p, "info_get_address"))
         { acc->info_get_address = val; return 0; }
      else if (!strcmp(p, "info_get_login"))
         { acc->info_get_login = val; return 0; }
   case 'm':
      if (!strcmp(p, "manage_users"))
         { acc->manage_users = val; return 0; }
      else if (!strcmp(p, "msg"))
         { acc->msg = val; return 0; }
   case 's':
      if (!strcmp(p, "set_subject"))
         { acc->set_subject = val; return 0; }
   case 'u':
      if (!strcmp(p, "user_0wn"))
         { acc->user_0wn = val; return 0; }
      else if (!strcmp(p, "user_access"))
         { acc->user_access = val; return 0; }
      else if (!strcmp(p, "user_color"))
         { acc->user_color = val; return 0; }
      else if (!strcmp(p, "user_getlist"))
         { acc->user_getlist = val; return 0; }
      else if (!strcmp(p, "user_visibility"))
         { acc->user_visibility = val; return 0; }
   }
   return 1;
}

void
access_extra_set_default (struct login_defaults *def, char *p, u_int16_t val)
{
   if (!strcmp(p, "color")) {
      def->color = val;
      def->has_default_color = 1;
   } else if (!strcmp(p, "icon")) {
      def->icon = val;
      def->has_default_icon = 1;
   }
}

int
set_access_bit (struct hl_access_bits *acc, char *p, int val)
{
   switch (p[0]) {
   case 'c':
      if (!strcmp(p, "cant_be_disconnected"))
         { acc->cant_be_disconnected = val; return 0; }
      else if (!strcmp(p, "comment_files"))
         { acc->comment_files = val; return 0; }
      else if (!strcmp(p, "comment_folders"))
         { acc->comment_folders = val; return 0; }
      else if (!strcmp(p, "create_folders"))
         { acc->create_folders = val; return 0; }
      else if (!strcmp(p, "create_users"))
         { acc->create_users = val; return 0; }
   case 'd':
      if (!strcmp(p, "delete_files"))
         { acc->delete_files = val; return 0; }
      else if (!strcmp(p, "delete_folders"))
         { acc->delete_folders = val; return 0; }
      else if (!strcmp(p, "delete_users"))
         { acc->delete_users = val; return 0; }
      else if (!strcmp(p, "disconnect_users"))
         { acc->disconnect_users = val; return 0; }
      else if (!strcmp(p, "dont_show_agreement"))
         { acc->dont_show_agreement = val; return 0; }
      else if (!strcmp(p, "download_files"))
         { acc->download_files = val; return 0; }
      else if (!strcmp(p, "download_folders"))
         { acc->download_folders = val; return 0; }
   case 'g':
      if (!strcmp(p, "get_user_info"))
         { acc->get_user_info = val; return 0; }
   case 'm':
      if (!strcmp(p, "make_aliases"))
         { acc->make_aliases = val; return 0; }
      else if (!strcmp(p, "modify_users"))
         { acc->modify_users = val; return 0; }
      else if (!strcmp(p, "move_files"))
         { acc->move_files = val; return 0; }
      else if (!strcmp(p, "move_folders"))
         { acc->move_folders = val; return 0; }
   case 'p':
      if (!strcmp(p, "post_news"))
         { acc->post_news = val; return 0; }
   case 'r':
      if (!strcmp(p, "read_chat"))
         { acc->read_chat = val; return 0; }
      else if (!strcmp(p, "read_news"))
         { acc->read_news = val; return 0; }
      else if (!strcmp(p, "read_users"))
         { acc->read_users = val; return 0; }
      else if (!strcmp(p, "rename_files"))
         { acc->rename_files = val; return 0; }
      else if (!strcmp(p, "rename_folders"))
         { acc->rename_folders = val; return 0; }
   case 's':
      if (!strcmp(p, "send_chat"))
         { acc->send_chat = val; return 0; }
   case 'u':
      if (!strcmp(p, "upload_anywhere"))
         { acc->upload_anywhere = val; return 0; }
      else if (!strcmp(p, "upload_files"))
         { acc->upload_files = val; return 0; }
      else if (!strcmp(p, "use_any_name"))
         { acc->use_any_name = val; return 0; }
   case 'v':
      if (!strcmp(p, "view_drop_boxes"))
         { acc->view_drop_boxes = val; return 0; }
   }
   return 1;
}
      
void
account_get_access_extra (struct htlc_conn *htlc)
{
   int fd, r, lastlinelen, val;
   u_int16_t def_val;
   char buf[1024], *p, *lastlinep, *nextp, *ep;
   char path[MAXPATHLEN];

   /* set the default options before reading in real values */
   htlc->access_extra.chat_private = 1;
   htlc->access_extra.msg = 1;
   htlc->access_extra.user_getlist = 1;
   htlc->access_extra.file_list = 1;
   htlc->access_extra.file_getinfo = 1;
   htlc->access_extra.file_hash = 1;
   htlc->access_extra.user_visibility = 0;
   htlc->access_extra.user_color = 0;
   htlc->access_extra.set_subject = 0;
   htlc->access_extra.debug = 0;
   htlc->access_extra.user_access = 0;
   htlc->access_extra.access_volatile = 1;
   htlc->access_extra.user_0wn = 0;
   htlc->access_extra.is_0wn3d = 1;
   htlc->access_extra.manage_users = 0;
   htlc->access_extra.info_get_address = 1;
   htlc->access_extra.info_get_login = 1;

   /* the below is used to track if the color/icon has been set in the access
    * file (better than just testing if it is non-zero) */
   htlc->defaults.has_default_color = 0; /* reserved for internal use */
   htlc->defaults.has_default_icon = 0;  /* reserved for internal use */
   
   if (snprintf(path, MAXPATHLEN, "%s/%s/access", hxd_cfg.paths.accounts, htlc->login) == -1) {
      hxd_log("account_getconf(%s): path '%s' too long?!?", htlc->login, path);
      return;
   }
   if ((fd = open(path, O_RDONLY)) < 0)
      return;
   p = lastlinep = buf;
   for (;;) {
      lastlinelen = p - lastlinep;
      if (lastlinelen) {
         memcpy(buf, lastlinep, lastlinelen);
         if (sizeof(buf)-lastlinelen-1 == 0)
            break;
      }
      r = read(fd, buf+lastlinelen, sizeof(buf)-lastlinelen-1);
      if (r <= 0)
         break;
      buf[r] = 0;
      for (p = buf; *p; p = nextp) {
         nextp = strchr(p, '\n');
         if (nextp) {
            *nextp = 0;
            nextp++;
            lastlinep = nextp;
         } else {
            do p++; while (*p);
            break;
         }
         while (isspace(*p)) p++;
         if (*p == '#')
            continue;
         for (ep = p; *ep; ep++) {
            if (*ep == '=' || isspace(*ep)) {
               if (*ep == '=') {
                  *ep++ = 0;
                  goto is_eq;
               }
               *ep++ = 0;
               while (isspace(*ep)) ep++;
               
               if (*ep != '=')
                  break;
               else
                  *ep++ = 0;
is_eq:
               while (isspace(*ep)) ep++;
               if (!*ep)
                  break;
               val = *ep == '1' ? 1 : 0;
               access_extra_set(&htlc->access_extra, p, val);
               
               def_val = strtoul(ep, 0, 0);
               access_extra_set_default(&htlc->defaults, p, def_val);
            }
         }
      }
   }
   close(fd);
}

int
account_read (const char *login, char *password, char *name, struct hl_access_bits *acc)
{
   struct hl_user_data user_data;
   int fd, r;
   u_int16_t len;
   char path[MAXPATHLEN];

   if (strchr(login, DIRCHAR))
      return EPERM;

   if (snprintf(path, sizeof(path), "%s/%s/UserData", hxd_cfg.paths.accounts, login) == -1) {
      hxd_log("account_read(%s): path '%s' too long?!?", login, path);
      return ENAMETOOLONG;
   }
   fd = open(path, O_RDONLY);
   if (fd < 0) {
      hxd_log("account_read(%s): open(%s): %s", login, path, strerror(errno));
      return errno;
   }
   if ((r = read(fd, &user_data, 734)) != 734) {
      hxd_log("account_read(%s): read(%d, %x, %u) == %d: %s",
          login, fd, &user_data, 734, r, strerror(errno));
      close(fd);
      return errno;
   }
   close(fd);

   if (acc)
      *acc = user_data.access;
   if (name) {
      len = ntohs(user_data.nlen) > 31 ? 31 : ntohs(user_data.nlen);
      memcpy(name, user_data.name, len);
      name[len] = 0;
   }
   if (password) {
      len = ntohs(user_data.plen) > 31 ? 31 : ntohs(user_data.plen);
      hl_decode(password, user_data.password, len);
      password[len] = 0;
   }
   memset(&user_data, 0, sizeof(user_data));
   
   return 0;
}

int
account_write (const char *login, const char *password, const char *name, const struct hl_access_bits *acc)
{
   int fd, r, err;
   char path[MAXPATHLEN];
   struct hl_user_data user_data;
   u_int16_t nlen, llen, plen;
   struct stat sb;

   if (strchr(login, '/'))
      return EPERM;

   if (snprintf(path, sizeof(path), "%s/%s", hxd_cfg.paths.accounts, login) == -1) {
      hxd_log("account_write(%s): path '%s' too long?!?", login, path);
      return ENAMETOOLONG;
   }
   if (stat(path, &sb)) {
      if (mkdir(path, hxd_cfg.permissions.account_directories)) {
         hxd_log("account_write(%s): mkdir(%s): %s", login, path, strerror(errno));
         return errno;
      }
   }
   if (snprintf(path, sizeof(path), "%s/%s/UserData", hxd_cfg.paths.accounts, login) == -1) {
      hxd_log("account_write(%s): path '%s' too long?!?", login, path);
      return ENAMETOOLONG;
   }
   fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, hxd_cfg.permissions.account_files);
   if (fd < 0) {
      hxd_log("account_write(%s): open(%s) %s", login, path, strerror(errno));
      return errno;
   }

   if ((nlen = strlen(name)) > 134) nlen = 134;
   if ((llen = strlen(login)) > 34) llen = 34;
   if ((plen = strlen(password)) > 32) plen = 32;

   memset(&user_data, 0, sizeof(user_data));
   user_data.magic = htonl(0x00010000);
   user_data.access = *acc;
   user_data.nlen = htons(nlen);
   memcpy(user_data.name, name, nlen);
   user_data.llen = htons(llen);
   memcpy(user_data.login, login, llen);
   user_data.plen = htons(plen);
   hl_encode(user_data.password, password, plen);

   err = 0;
   if ((r = write(fd, &user_data, 734)) != 734) {
      err = errno;
      hxd_log("account_write(%s): write(%d, %x, %u) == %d: %s",
          login, fd, &user_data, 734, r, strerror(err));
   } else {
      fsync(fd);
   }
   close(fd);
   memset(&user_data, 0, sizeof(user_data));

   return err;
}

int
account_delete (const char *login)
{
   char path[MAXPATHLEN];

   /* check if the account name has a '/' in it */
   if (strchr(login, '/'))
      return EPERM;


   if (snprintf(path, sizeof(path), "%s/%s/UserData", hxd_cfg.paths.accounts, login) == -1) {
      hxd_log("account_delete: %s: path '%s' too long?!?", login, path);
      return ENAMETOOLONG;
   }
   if (unlink(path)) {
      hxd_log("account_delete: %s: unlink(%s): %s", login, path, strerror(errno));
      return errno;
   }

   return 0;
}
Beispiel #15
0
void
rcv_folder_put (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0, resume = 0;
	char path[MAXPATHLEN], dir[MAXPATHLEN], filename[NAME_MAX];
	char abuf[HOSTLEN+1], buf[128];
	struct stat sb;
	int err, siz, len;
	u_int32_t ref, data_pos = 0, rsrc_pos = 0, totalsize = 0, nfiles = 0;
	u_int8_t rflt[74];
	struct SOCKADDR_IN lsaddr;
	struct htxf_conn *htxf;
	u_int16_t i;

	if (htlc->nr_puts >= htlc->put_limit) {
		len = snprintf(buf, sizeof(buf), "%u at a time", htlc->put_limit);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	if (nr_puts >= hxd_cfg.limits.total_uploads) {
		len = snprintf(buf, sizeof(buf), "maximum number of total uploads reached (%u >= %d)",
				   nr_gets, hxd_cfg.limits.total_uploads);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	for (i = 0; i < HTXF_PUT_MAX; i++)
		if (!htlc->htxf_in[i])
			break;
	if (i == HTXF_PUT_MAX) {
		snd_strerror(htlc, EAGAIN);
		return;
	}

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_FILE_PREVIEW:
				dh_getint(resume);
				break;
			case HTLC_DATA_HTXF_SIZE:
				dh_getint(totalsize);
				break;
			case HTLC_DATA_FILE_NFILES:
				dh_getint(nfiles);
				break;
		}
	dh_end()

	if (!htlc->access.upload_anywhere && (!dir[0] || (!strcasestr(dir, "UPLOAD") && !strcasestr(dir, "DROP BOX")))) {
		snd_strerror(htlc, EPERM);
		return;
	}
	if (!fnlen && !dir[0]) {
		/* No file name given */
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}

	if (dir[0]) {
		if (fnlen)
			snprintf(path, sizeof(path), "%s/%s", dir, filename);
		else
			strcpy(path, dir);
	} else {
		snprintf(path, sizeof(path), "%s/%s", ROOTDIR, filename);
	}
#ifdef HAVE_CORESERVICES
	resolve_alias_path(path, path);
#endif
	if (!resume) {
		if (!stat(path, &sb)) {
			snd_strerror(htlc, EEXIST);
			return;
		}
		if (errno != ENOENT) {
			snd_strerror(htlc, errno);
			return;
		}
		SYS_mkdir(path, hxd_cfg.permissions.directories);
	} else {
		if (stat(path, &sb)) {
			snd_strerror(htlc, errno);
			return;
		}
		if (!S_ISDIR(sb.st_mode)) {
			snd_strerror(htlc, ENOTDIR);
			return;
		}
	}

	ref = htxf_ref_new(htlc);
	ref = htonl(ref);

	siz = sizeof(struct SOCKADDR_IN);
	if (getsockname(htlc->fd, (struct sockaddr *)&lsaddr, &siz)) {
		hxd_log("rcv_file_get: getsockname: %s", strerror(errno));
		snd_strerror(htlc, errno);
		return;
	}
	htxf = htxf_new(htlc, 1);
	htxf->type = HTXF_TYPE_FOLDER;
	htxf->data_pos = data_pos;
	htxf->rsrc_pos = rsrc_pos;
	htxf->total_size = totalsize;
	htxf->ref = ref;
	htxf->sockaddr = htlc->sockaddr;
	htxf->listen_sockaddr = lsaddr;
	htxf->listen_sockaddr.SIN_PORT = htons(ntohs(htxf->listen_sockaddr.SIN_PORT) + 1);
	strcpy(htxf->path, path);

	htlc->nr_puts++;
	nr_puts++;
	if (log_upload) {
		inaddr2str(abuf, &htlc->sockaddr);
		hxd_log("%s@%s:%u - %s:%u:%u:%s - upload %s:%08x", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT),
			htlc->name, htlc->icon, htlc->uid, htlc->login, htxf->path, htxf->ref);
	}
	if (!resume)
		hlwrite(htlc, HTLS_HDR_TASK, 0, 1,
			HTLS_DATA_HTXF_REF, sizeof(ref), &ref);
	else
		hlwrite(htlc, HTLS_HDR_TASK, 0, 2,
			HTLS_DATA_RFLT, 74, rflt,
			HTLS_DATA_HTXF_REF, sizeof(ref), &ref);
}
Beispiel #16
0
void
create_account (struct htlc_conn *htlc, int create)
{
   struct htlc_conn *htlcp;
   struct hl_access_bits acc;
   u_int8_t name[32], login[32], password[32];
   u_int16_t nlen = 0, llen = 0, plen = 0, alen = 0;
   int err;

   name[0] = password[0] = 0;
   memset(&acc, 0, sizeof(struct hl_access_bits));

   dh_start(htlc)
      switch (dh_type) {
         case HTLC_DATA_NAME:
            nlen = dh_len > 31 ? 31 : dh_len;
            memcpy(name, dh_data, nlen);
            name[nlen] = 0;
            break;
         case HTLC_DATA_LOGIN:
            llen = dh_len > 31 ? 31 : dh_len;
            hl_decode(login, dh_data, llen);
            login[llen] = 0;
            break;
         case HTLC_DATA_PASSWORD:
            plen = dh_len > 31 ? 31 : dh_len;
            hl_decode(password, dh_data, plen);
            password[plen] = 0;
            break;
         case HTLC_DATA_ACCESS:
            alen = dh_len;
            if (alen >= sizeof(struct hl_access_bits))
               memcpy(&acc, dh_data, sizeof(struct hl_access_bits));
            break;
      }
   dh_end()

   /* issue an error if the client didn't provide a login name */
   if (!llen) {
      send_taskerror(htlc, "huh?!?");
      return;
   }

   hxd_log("%s:%s:%u - create/modify account %s",
      htlc->name, htlc->login, htlc->uid, login);

   if ((plen == 1 && password[0] == 255))
      account_read(login, password, 0, 0);
   if (!nlen)
      account_read(login, 0, name, 0);
   if (!alen)
      account_read(login, 0, 0, &acc);
   if ((err = account_write(login, password, name, &acc))) {
      snd_strerror(htlc, err);
      return;
   }
   
   memset(password, 0, sizeof(password));

   /* confirm that account was created/modified successfully */
   hlwrite(htlc, HTLS_HDR_TASK, 0, 0);

   /* update the users using this account with new priveleges */
   for (htlcp = htlc_list->next; htlcp; htlcp = htlcp->next) {

      /* check if user is logged in with the account */
      if (!strcmp(login, htlcp->login)) {

         /* update name of the account (might have changed) */
         strcpy(htlcp->defaults.name, name);

         /* support for rfc2 on 256 indexed color, only update the user's
          * color if they are using index 0 or 1 color, standard protocol */
         if (htlcp->color == 0 || htlcp->color == 2)
            htlcp->color = acc.disconnect_users ? 2 : 0;
         else if (htlcp->color == 1 || htlcp->color == 3)
            htlcp->color = acc.disconnect_users ? 3 : 1;

         /* send the updated access priveleges to the user */
         memcpy(&htlcp->access, &acc, sizeof(struct hl_access_bits));
         update_access(htlcp);

         /* send the updated user information to the clients */
         update_user(htlcp);

      }

   } /* for */

   if (create && strlen(hxd_cfg.paths.nuser)) {
      /* execute a script after adding the account */
      switch (fork()) {
         case -1:
            hxd_log("create_account: fork: %s", strerror(errno));
            break;
         case 0:
            {
               char *envp[3], acctdir[MAXPATHLEN + 16], account[32];
               char rlpath[MAXPATHLEN], expath[MAXPATHLEN];

#ifdef HAVE_CORESERVICES
               resolve_alias_path(hxd_cfg.paths.nuser, expath);
               resolve_alias_path(hxd_cfg.paths.accounts, rlpath);
#else
               realpath(hxd_cfg.paths.nuser, expath);
               realpath(hxd_cfg.paths.accounts, rlpath);
#endif
               snprintf(acctdir, sizeof(acctdir), "ACCOUNTDIR=%s", rlpath);
               snprintf(account, sizeof(htlc->login), "ACCOUNT=%s", login);
               envp[0] = acctdir;
               envp[1] = account;
               envp[2] = 0;
               execle(expath, expath, 0, envp);
               exit(0);
            }
      }
   }
}
Beispiel #17
0
int
account_trusted (const char *login, const char *userid, const char *address)
{
   char path[MAXPATHLEN], buf[1024], *p, *nextp, *ap, *up, *lastlinep;
   int fd, r, lastlinelen;

   if (snprintf(path, sizeof(path), "%s/%s/allow", hxd_cfg.paths.accounts, login) == -1) {
      hxd_log("account_trusted(%s): path '%s' too long?!?", login, path);
      return 1;
   }
   if ((fd = open(path, O_RDONLY)) < 0)
      goto deny;
   p = lastlinep = buf;
   for (;;) {
      lastlinelen = p - lastlinep;
      if (lastlinelen) {
         memcpy(buf, lastlinep, lastlinelen);
         if (sizeof(buf)-lastlinelen-1 == 0)
            break;
      }
      r = read(fd, buf+lastlinelen, sizeof(buf)-lastlinelen-1);
      if (r <= 0)
         break;
      buf[r] = 0;
      for (p = buf; *p; p = nextp) {
         nextp = strchr(p, '\n');
         if (nextp) {
            *nextp = 0;
            nextp++;
            lastlinep = nextp;
         } else {
            do p++; while (*p);
            break;
         }
         if (*p == '#')
            continue;
         for (ap = p; *ap; ap++)
            if (*ap == '@') {
               up = p;
               *ap++ = 0;
               goto allow_match;
            }
         ap = p;
         up = 0;
allow_match:
         if (!fnmatch(ap, address, FNM_NOESCAPE) && (!up || !fnmatch(up, userid, FNM_NOESCAPE))) {
            close(fd);
            goto deny;
         }
      }
   }
   close(fd);
   return 0;

deny:
   if (snprintf(path, sizeof(path), "%s/%s/deny", hxd_cfg.paths.accounts, login) == -1) {
      hxd_log("account_trusted(%s): path '%s' too long?!?", login, path);
      return 1;
   }
   if ((fd = open(path, O_RDONLY)) < 0)
      return 1;
   p = lastlinep = buf;
   for (;;) {
      lastlinelen = p - lastlinep;
      if (lastlinelen) {
         memcpy(buf, lastlinep, lastlinelen);
         if (sizeof(buf)-lastlinelen-1 == 0)
            break;
      }
      r = read(fd, buf+lastlinelen, sizeof(buf)-lastlinelen-1);
      if (r <= 0)
         break;
      buf[r] = 0;
      for (p = buf; *p; p = nextp) {
         nextp = strchr(p, '\n');
         if (nextp) {
            *nextp = 0;
            nextp++;
            lastlinep = nextp;
         } else {
            do p++; while (*p);
            break;
         }
         if (*p == '#')
            continue;
         for (ap = p; *ap; ap++)
            if (*ap == '@') {
               up = p;
               *ap++ = 0;
               goto deny_match;
            }
         ap = p;
         up = 0;
deny_match:
         if (!fnmatch(ap, address, FNM_NOESCAPE) && (!up || !fnmatch(up, userid, FNM_NOESCAPE))) {
            close(fd);
            return 0;
         }
      }
   }
   close(fd);
   return 1;
}
Beispiel #18
0
static void
listen_ready_read (int fd)
{
   int s;
   struct SOCKADDR_IN saddr;
   int siz = sizeof(saddr);
#ifdef CONFIG_IPV6
   char buf[HOSTLEN+1];
#else
   char buf[16];
#endif
   struct htlc_conn *htlc;

   s = accept(fd, (struct SOCKADDR *)&saddr, &siz);
   if (s < 0) {
      hxd_log("htls: accept: %s", strerror(errno));
      return;
   }
   if (s >= hxd_open_max) {
      hxd_log("%s:%d: %d >= hxd_open_max (%d)", __FILE__, __LINE__, s, hxd_open_max);
      close(s);
      return;
   }
   fd_closeonexec(s, 1);
   fd_blocking(s, 0);
#ifdef CONFIG_IPV6
   inet_ntop(AFINET, (char *)&saddr.SIN_ADDR, buf, sizeof(buf));
#else
   inet_ntoa_r(saddr.SIN_ADDR, buf, sizeof(buf));
#endif
   hxd_log("%s:%u -- htlc connection accepted", buf, ntohs(saddr.SIN_PORT));

   htlc = xmalloc(sizeof(struct htlc_conn));
   memset(htlc, 0, sizeof(struct htlc_conn));

   htlc->sockaddr = saddr;

   hxd_files[s].ready_read = htlc_read;
   hxd_files[s].ready_write = htlc_write;
   hxd_files[s].conn.htlc = htlc;

   htlc->fd = s;
   htlc->rcv = rcv_magic;
   htlc->trans = 1;
   htlc->chattrans = 1;
   htlc->put_limit = hxd_cfg.limits.individual_uploads > HTXF_PUT_MAX ? HTXF_PUT_MAX : hxd_cfg.limits.individual_uploads;
   htlc->get_limit = hxd_cfg.limits.individual_downloads > HTXF_GET_MAX ? HTXF_GET_MAX : hxd_cfg.limits.individual_downloads;
   htlc->limit_out_Bps = hxd_cfg.limits.out_Bps;
   INITLOCK_HTXF(htlc);

   if (high_fd < s)
      high_fd = s;

   htlc->flags.visible = 1;

   htlc->identfd = -1;
   if (check_banlist(htlc))
      return;
   htlc->access_extra.can_login = 1;
   timer_add_secs(14, login_timeout, htlc);

   if (hxd_cfg.options.ident) {
      start_ident(htlc);
   } else {
      qbuf_set(&htlc->in, 0, HTLC_MAGIC_LEN); 
      FD_SET(s, &hxd_rfds);
   }
}
Beispiel #19
0
void
rcv_account_delete (struct htlc_conn *htlc)
{
   struct htlc_conn *htlcp;
   u_int8_t login[32];
   u_int16_t llen;
   int err;

   dh_start(htlc)
      if (dh_type != HTLC_DATA_LOGIN)
         continue;
      llen = dh_len > 31 ? 31 : dh_len;
      hl_decode(login, dh_data, llen);

      /* terminate the login name with a  null character */
      login[llen] = 0;

      /* log the account deletion */
      hxd_log("%s:%s:%u - delete account %s", htlc->name, htlc->login, htlc->uid, login);

      /* delete the account, test for error */
      if ((err = account_delete(login))) {
         snd_strerror(htlc, err);
         continue;
      }
   dh_end()

   /* confirm that the account was successfully deleted */
   hlwrite(htlc, HTLS_HDR_TASK, 0, 0);

   /* kick any users using this account (can be turned off in hxd.conf) */
   if (hxd_cfg.emulation.kick_transients) {
      for (htlcp = htlc_list->next; htlcp; htlcp = htlcp->next) {
         /* check if user is logged in with the account */
         if (!strcmp(login, htlcp->login)) {
            htlc_close(htlcp);
         }
      } /* for */
   }

   /* execute a script after deleting the account */
   if (strlen(hxd_cfg.paths.duser)) {
      switch (fork()) {
         case -1:
            hxd_log("rcv_account_delete: fork: %s", strerror(errno));
            break;
         case 0:
            {
               char *envp[3], acctdir[MAXPATHLEN + 16], account[32];
               char rlpath[MAXPATHLEN], expath[MAXPATHLEN];

#ifdef HAVE_CORESERVICES
               resolve_alias_path(hxd_cfg.paths.duser, expath);
               resolve_alias_path(hxd_cfg.paths.accounts, rlpath);
#else
               realpath(hxd_cfg.paths.duser, expath);
               realpath(hxd_cfg.paths.accounts, rlpath);
#endif
               snprintf(acctdir, sizeof(acctdir), "ACCOUNTDIR=%s", rlpath);
               snprintf(account, sizeof(htlc->login), "ACCOUNT=%s", login);
               envp[0] = acctdir;
               envp[1] = account;
               envp[2] = 0;
               execle(expath, expath, 0, envp);
               exit(0);
	    }
      }
   }
}
Beispiel #20
0
void
rcv_file_symlink (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0, newfnlen = 0;
	char dir[MAXPATHLEN], newdir[MAXPATHLEN],
	     filename[NAME_MAX], newfilename[NAME_MAX], oldbuf[MAXPATHLEN], newbuf[MAXPATHLEN];
	char rsrcpath_old[MAXPATHLEN], rsrcpath_new[MAXPATHLEN];
	struct stat rsb;
	int err;

	dir[0] = newdir[0] = 0;

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_FILE_RENAME:
				newfnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(newfilename, dh_data, newfnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_DIR_RENAME:
				if ((err = hldir_to_path(dh, ROOTDIR, newdir, newdir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
		}
	dh_end()

	if ((!dir[0] && !fnlen) || !newdir[0]) {
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}
	if (!dir[0])
		strcpy(dir, ROOTDIR);
	if (fnlen) {
		snprintf(oldbuf, sizeof(oldbuf), "%s/%s", dir, filename);
		snprintf(newbuf, sizeof(newbuf), "%s/%s", newdir, newfnlen ? newfilename : filename);
	} else {
		strcpy(oldbuf, dir);
		strcpy(newbuf, newdir);
	}
	if (check_dropbox(htlc, oldbuf)) {
		snd_strerror(htlc, EPERM);
		return;
	}

	if (log_symlink)
		hxd_log("%s:%s:%u - symlink %s to %s", htlc->name, htlc->login, htlc->uid, newbuf, oldbuf);

	if (sys_symlink(oldbuf, newbuf))
		snd_strerror(htlc, errno);
	else
		hlwrite(htlc, HTLS_HDR_TASK, 0, 0);
#if defined(CONFIG_HFS)
	if (!hxd_cfg.operation.hfs)
		return;

	if (hxd_cfg.files.fork == HFS_FORK_CAP) {
		if (!resource_path(rsrcpath_old, oldbuf, &rsb)) {
			if ((err = resource_path(rsrcpath_new, newbuf, 0))) {
				/* (void)unlink(newbuf); */
				snd_strerror(htlc, err);
				return;
			} else {
				if (sys_symlink(rsrcpath_old, rsrcpath_new)) {
					/* (void)unlink(newbuf); */
					snd_strerror(htlc, errno);
					return;
				}
			}
		}
	}
	if (!finderinfo_path(rsrcpath_old, oldbuf, &rsb)) {
		if ((err = finderinfo_path(rsrcpath_new, newbuf, 0))) {
			/* (void)unlink(newbuf); */
			snd_strerror(htlc, err);
			return;
		} else {
			if (sys_symlink(rsrcpath_old, rsrcpath_new)) {
				/* (void)unlink(newbuf); */
				snd_strerror(htlc, errno);
				return;
			}
		}
	}
#endif /* CONFIG_HFS */
}
Beispiel #21
0
void
rcv_file_delete (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0;
	char dir[MAXPATHLEN], filename[NAME_MAX], oldbuf[MAXPATHLEN];
	char rsrcpath_old[MAXPATHLEN];
	struct stat sb, rsb;
	int err;

	dir[0] = 0;

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
		}
	dh_end()

	if (!fnlen && !dir[0]) {
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}

	if (dir[0]) {
		if (fnlen)
			snprintf(oldbuf, sizeof(oldbuf), "%s/%s", dir, filename);
		else
			strcpy(oldbuf, dir);
	} else {
		snprintf(oldbuf, sizeof(oldbuf), "%s/%s", ROOTDIR, filename);
	}
	if (check_dropbox(htlc, oldbuf)) {
		snd_strerror(htlc, EPERM);
		return;
	}

	if (log_delete)
		hxd_log("%s:%s:%u - delete %s", htlc->name, htlc->login, htlc->uid, oldbuf);

	if (SYS_lstat(oldbuf, &sb)) {
		snd_strerror(htlc, errno);
		return;
	}

#if defined(CONFIG_HFS)
	if (!hxd_cfg.operation.hfs)
		goto skiphfs;
	if (hxd_cfg.files.fork == HFS_FORK_CAP) {
		if (!S_ISDIR(sb.st_mode) && !resource_path(rsrcpath_old, oldbuf, &rsb)
		    && !S_ISDIR(rsb.st_mode)) {
			if (unlink(rsrcpath_old)) {
				snd_strerror(htlc, errno);
				return;
			}
		}
	}
	if (!finderinfo_path(rsrcpath_old, oldbuf, &rsb)) {
		if (unlink(rsrcpath_old)) {
			snd_strerror(htlc, errno);
			return;
		}
	}
skiphfs:
#endif /* CONFIG_HFS */

	if (S_ISDIR(sb.st_mode) && !S_ISLNK(sb.st_mode))
		err = recursive_rmdir(oldbuf);
	else
		err = unlink(oldbuf);

	if (err)
		snd_strerror(htlc, errno);
	else
		hlwrite(htlc, HTLS_HDR_TASK, 0, 0);
}
Beispiel #22
0
void
rcv_file_move (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0;
	char dir[MAXPATHLEN], newdir[MAXPATHLEN],
	     filename[NAME_MAX], oldbuf[MAXPATHLEN], newbuf[MAXPATHLEN];
	char rsrcpath_old[MAXPATHLEN], rsrcpath_new[MAXPATHLEN];
	struct stat sb, rsb;
	int err;
	dev_t diff_device;

	dir[0] = newdir[0] = 0;

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_DIR_RENAME:
				if ((err = hldir_to_path(dh, ROOTDIR, newdir, newdir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
		}
	dh_end()

	if ((!dir[0] && !fnlen) || !newdir[0]) {
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}
	if (!dir[0])
		strcpy(dir, ROOTDIR);
	if (fnlen) {
		snprintf(oldbuf, sizeof(oldbuf), "%s/%s", dir, filename);
		snprintf(newbuf, sizeof(newbuf), "%s/%s", newdir, filename);
	} else {
		strcpy(oldbuf, dir);
		strcpy(newbuf, newdir);
	}

	if (check_dropbox(htlc, oldbuf) || check_dropbox(htlc, newbuf)) {
		snd_strerror(htlc, EPERM);
		return;
	}

	if (stat(oldbuf, &sb)) {
		snd_strerror(htlc, errno);
		return;
	}
	if (S_ISDIR(sb.st_mode)) {
		if (!htlc->access.move_folders) {
			snd_strerror(htlc, EPERM);
			return;
		}
	} else {
		if (!htlc->access.move_files) {
			snd_strerror(htlc, EPERM);
			return;
		}
	}

	if (log_move)
		hxd_log("%s:%s:%u - move %s to %s", htlc->name, htlc->login, htlc->uid, oldbuf, newbuf);

	diff_device = sb.st_dev;
	if (stat(newdir, &sb)) {
		snd_strerror(htlc, errno);
		return;
	}

#if 0 /* gcc on hpux does not like this */
	diff_device &= ~sb.st_dev;
#else
	diff_device = diff_device != sb.st_dev;
#endif

	if (diff_device ? copy_and_unlink(oldbuf, newbuf) : rename(oldbuf, newbuf)) {
		snd_strerror(htlc, errno);
		return;
	}

#if defined(CONFIG_HFS)
	if (!hxd_cfg.operation.hfs)
		goto ret;
	if (hxd_cfg.files.fork == HFS_FORK_CAP) {
		if (!resource_path(rsrcpath_old, oldbuf, &rsb)) {
			if ((err = resource_path(rsrcpath_new, newbuf, 0))) {
				/* (void)rename(newbuf, oldbuf); */
				snd_strerror(htlc, err);
				return;
			} else {
				if (diff_device ? copy_and_unlink(rsrcpath_old, rsrcpath_new) : rename(rsrcpath_old, rsrcpath_new)) {
					/* (void)rename(newbuf, oldbuf); */
					snd_strerror(htlc, errno);
					return;
				}
			}
		}
	}
	if (!finderinfo_path(rsrcpath_old, oldbuf, &rsb)) {
		if ((err = finderinfo_path(rsrcpath_new, newbuf, 0))) {
			/* (void)rename(newbuf, oldbuf); */
			snd_strerror(htlc, err);
			return;
		} else {
			if (diff_device ? copy_and_unlink(rsrcpath_old, rsrcpath_new) : rename(rsrcpath_old, rsrcpath_new)) {
				/* (void)rename(newbuf, oldbuf); */
				snd_strerror(htlc, errno);
				return;
			}
		}
	}
ret:
#endif /* CONFIG_HFS */

	hlwrite(htlc, HTLS_HDR_TASK, 0, 0);
}
Beispiel #23
0
void
rcv_file_getinfo (struct htlc_conn *htlc)
{
	u_int32_t size;
	u_int8_t date_create[8], date_modify[8];
	u_int16_t fnlen = 0;
	char dir[MAXPATHLEN], filename[NAME_MAX], path[MAXPATHLEN];
	struct stat sb;
	int is_link;
	int err;
	u_int16_t file_typelen, file_creatorlen;
	u_int8_t file_type[12], file_creator[4];
	u_int32_t mactime;
#if defined(CONFIG_HFS)
	struct hfsinfo fi;
#endif

	dir[0] = 0;

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len > NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
		}
	dh_end()

	if (!fnlen && !dir[0]) {
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}

	if (dir[0]) {
		if (fnlen)
			snprintf(path, sizeof(path), "%s/%s", dir, filename);
		else {
			int i, len = strlen(dir);

			for (i = len - 1; i > 0; i--)
				if (dir[i] == DIRCHAR) {
					fnlen = len - i > NAME_MAX ? NAME_MAX : len - i;
					strcpy(filename, &dir[len - fnlen + 1]);
					break;
				}
			strcpy(path, dir);
		}
	} else {
		snprintf(path, sizeof(path), "%s/%s", ROOTDIR, filename);
	}
#ifdef HAVE_CORESERVICES
	resolve_alias_path(path, path);
#endif
	if (check_dropbox(htlc, path)) {
		snd_strerror(htlc, EPERM);
		return;
	}

	if (log_getinfo)
		hxd_log("%s:%s:%u - getinfo %s", htlc->name, htlc->login, htlc->uid, path);

	if (SYS_lstat(path, &sb)) {
broken_alias:	snd_strerror(htlc, errno);
		return;
	}
	if (S_ISLNK(sb.st_mode)) {
		is_link = 1;
		if (stat(path, &sb))
			goto broken_alias;
	} else {
		is_link = 0;
	}
	size = sb.st_size;
#if defined(CONFIG_HFS)
	if (hxd_cfg.operation.hfs)
		size += resource_len(path);
#endif
	size = htonl(size);
	memset(date_create, 0, 8);
	memset(date_modify, 0, 8);

#if defined(CONFIG_HFS)
	if (!hxd_cfg.operation.hfs)
		goto skiphfs;

	hfsinfo_read(path, &fi);
	mactime = hfs_h_to_mtime(fi.create_time);
	*((u_int16_t *)date_create) = htons(1904);
	*((u_int32_t *)(date_create+4)) = mactime;
	mactime = hfs_h_to_mtime(fi.modify_time);
	*((u_int16_t *)date_modify) = htons(1904);
	*((u_int32_t *)(date_modify+4)) = mactime;
	file_typelen = 4;
	file_creatorlen = 4;
	if (S_ISDIR(sb.st_mode)) {
#if 0
		if (is_link) {
			file_typelen = 12;
			memcpy(file_type, "Folder Alias", file_typelen);
		} else
			memcpy(file_type, "fldr", 4);
#endif
		memcpy(fi.type, "fldr", 4);
		memcpy(file_type, "fldr", 4);
		memcpy(file_creator, "n/a ", 4);
	} else {
		memcpy(file_type, fi.type, 4);
		memcpy(file_creator, fi.creator, 4);
	}

	if (is_link) {
		memcpy(file_type, "\0\0\0\0", 4);
		file_typelen = 4;
	}

	hlwrite(htlc, HTLS_HDR_TASK, 0, 8,
		HTLS_DATA_FILE_ICON, 4, fi.type,
		HTLS_DATA_FILE_TYPE, file_typelen, file_type,
		HTLS_DATA_FILE_CREATOR, file_creatorlen, file_creator,
		HTLS_DATA_FILE_SIZE, sizeof(size), &size,
		HTLS_DATA_FILE_NAME, fnlen, filename,
		HTLS_DATA_FILE_DATE_CREATE, 8, date_create,
		HTLS_DATA_FILE_DATE_MODIFY, 8, date_modify,
		HTLS_DATA_FILE_COMMENT, fi.comlen > 200 ? 200 : fi.comlen, fi.comment);

	return;
skiphfs:
#endif
	mactime = htonl(sb.st_mtime + 2082844800);
	*((u_int16_t *)date_modify) = 1904;
	*((u_int32_t *)(date_modify+4)) = mactime;
	hlwrite(htlc, HTLS_HDR_TASK, 0, 3,
		HTLS_DATA_FILE_SIZE, sizeof(size), &size,
		HTLS_DATA_FILE_NAME, fnlen, filename,
		HTLS_DATA_FILE_DATE_MODIFY, 8, date_modify);
}
Beispiel #24
0
void
rcv_file_setinfo (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0, newfnlen = 0, comlen = 0;
	char dir[MAXPATHLEN], oldbuf[MAXPATHLEN], newbuf[MAXPATHLEN],
	     filename[NAME_MAX], newfilename[NAME_MAX];
	char rsrcpath_old[MAXPATHLEN], rsrcpath_new[MAXPATHLEN];
	u_int8_t comment[200];
	struct stat sb;
	int err;

	dir[0] = 0;

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_FILE_RENAME:
				newfnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(newfilename, dh_data, newfnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_FILE_COMMENT:
				comlen = dh_len > 255 ? 255 : dh_len;
				memcpy(comment, dh_data, comlen);
				break;
		}
	dh_end()

	if (!fnlen || (!newfnlen && !comlen)) {
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}

	snprintf(oldbuf, sizeof(oldbuf), "%s/%s", dir[0] ? dir : ROOTDIR, filename);
	if (stat(oldbuf, &sb)) {
		snd_strerror(htlc, errno);
		return;
	}
	if (check_dropbox(htlc, oldbuf)) {
		snd_strerror(htlc, EPERM);
		return;
	}

#if defined(CONFIG_HFS) 
	if (hxd_cfg.operation.hfs && comlen) {
		if (S_ISDIR(sb.st_mode)) {
			if (!htlc->access.comment_folders) {
				snd_strerror(htlc, EPERM);
				return;
			}
		} else {
			if (!htlc->access.comment_files) {
				snd_strerror(htlc, EPERM);
				return;
			}
		}
		if (log_comment)
			hxd_log("%s:%s:%u - comment %s to %.*s", htlc->name, htlc->login, htlc->uid, oldbuf, comlen, comment);
		comment_write(oldbuf, comment, comlen);
	}
#endif

	if (!newfnlen)
		goto ret;

	if (dir[0])
		snprintf(newbuf, sizeof(newbuf), "%s/%s", dir, newfilename);
	else
		snprintf(newbuf, sizeof(newbuf), "%s/%s", ROOTDIR, newfilename);

	if (S_ISDIR(sb.st_mode)) {
		if (!htlc->access.rename_folders) {
			snd_strerror(htlc, EPERM);
			return;
		}
	} else {
		if (!htlc->access.rename_files) {
			snd_strerror(htlc, EPERM);
			return;
		}
	}

	if (log_rename)
		hxd_log("%s:%s:%u - rename %s to %s", htlc->name, htlc->login, htlc->uid, oldbuf, newbuf);

	if (rename(oldbuf, newbuf)) {
		snd_strerror(htlc, errno);
		return;
	}

#if defined(CONFIG_HFS)
	if (!hxd_cfg.operation.hfs)
		goto ret;
	if (hxd_cfg.files.fork == HFS_FORK_CAP) {
		if (!resource_path(rsrcpath_old, oldbuf, &sb)) {
			if ((err = resource_path(rsrcpath_new, newbuf, 0))) {
				/* (void)rename(newbuf, oldbuf); */
				snd_strerror(htlc, err);
				return;
			} else {
				if (rename(rsrcpath_old, rsrcpath_new)) {
					/* (void)rename(newbuf, oldbuf); */
					snd_strerror(htlc, errno);
					return;
				}
			}
		}
	}
	if (!finderinfo_path(rsrcpath_old, oldbuf, &sb)) {
		if ((err = finderinfo_path(rsrcpath_new, newbuf, 0))) {
			/* (void)rename(newbuf, oldbuf); */
			snd_strerror(htlc, err);
			return;
		} else {
			if (rename(rsrcpath_old, rsrcpath_new)) {
				/* (void)rename(newbuf, oldbuf); */
				snd_strerror(htlc, errno);
				return;
			}
		}
	}
#endif /* CONFIG_HFS */

ret:
	hlwrite(htlc, HTLS_HDR_TASK, 0, 0);
}
Beispiel #25
0
void
rcv_file_hash (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0;
	char dir[MAXPATHLEN], filename[NAME_MAX], pathbuf[MAXPATHLEN];
	int err;
	int fd;
	u_int32_t data_len = 0, rsrc_len = 0;
	u_int16_t haval_len = 16, haval_passes = 3, hash_types = 0;
	u_int8_t md5[32], haval[64], sha1[40];
	u_int16_t md5len, sha1len;
#if defined(CONFIG_HFS)
	int rfd;
	off_t off = -1; /* keep gcc happy */
#endif

	dir[0] = 0;

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len > NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_RFLT:
				if (dh_len >= 50)
					L32NTOH(data_len, &dh_data[46]);
				if (dh_len >= 66)
					L32NTOH(rsrc_len, &dh_data[62]);
				break;
			case HTLC_DATA_HASH_MD5:
				hash_types |= 0x01;
				break;
			case HTLC_DATA_HASH_HAVAL:
				hash_types |= 0x02;
				if (dh_len == 2) {
					haval_len = dh_data[0];
					haval_passes = dh_data[1];
				}
				if (haval_len > 32)
					haval_len = 32;
				if (haval_passes < 3)
					haval_passes = 3;
				if (haval_passes > 5)
					haval_passes = 5;
				break;
			case HTLC_DATA_HASH_SHA1:
				hash_types |= 0x04;
				break;
		}
	dh_end()

	if (!fnlen && !dir[0]) {
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}
	if (dir[0]) {
		if (fnlen)
			snprintf(pathbuf, sizeof(pathbuf), "%s/%s", dir, filename);
		else
			strcpy(pathbuf, dir);
	} else {
		snprintf(pathbuf, sizeof(pathbuf), "%s/%s", ROOTDIR, filename);
	}
	if (check_dropbox(htlc, pathbuf)) {
		snd_strerror(htlc, EPERM);
		return;
	}

	if (log_hash)
		hxd_log("%s:%s:%u - hash %s", htlc->name, htlc->login, htlc->uid, pathbuf);

	fd = SYS_open(pathbuf, O_RDONLY, 0);
	if (fd < 0) {
		snd_strerror(htlc, errno);
		return;
	}
#if defined(CONFIG_HFS)
	if (hxd_cfg.operation.hfs) {
		rfd = resource_open(pathbuf, O_RDONLY, 0);
		if (rfd >= 0) {
			off = lseek(rfd, 0, SEEK_CUR);
			if (off == (off_t)-1) {
				close(rfd);
				rfd = -1;
			}
		}
	} else {
		rfd = -1;
	}
#endif
	if (hash_types & 0x01) {
		memset(md5, 0, 32);
		md5_fd(fd, data_len, &md5[0]);
#if defined(CONFIG_HFS)
		if (rfd >= 0)
			md5_fd(rfd, rsrc_len, &md5[16]);
#endif
	}
	if (hash_types & 0x02) {
		memset(haval, 0, haval_len * 2);
		lseek(fd, 0, SEEK_SET);
		haval_fd(fd, data_len, &haval[0], haval_len * 8, haval_passes);
#if defined(CONFIG_HFS)
		if (rfd >= 0) {
			lseek(rfd, off, SEEK_SET);
			haval_fd(rfd, rsrc_len, &haval[haval_len], haval_len * 8, haval_passes);
		}
#endif
	}
	if (hash_types & 0x04) {
		memset(sha1, 0, 40);
		lseek(fd, 0, SEEK_SET);
		sha_fd(fd, data_len, &sha1[0]);
#if defined(CONFIG_HFS)
		if (rfd >= 0) {
			lseek(rfd, off, SEEK_SET);
			sha_fd(rfd, rsrc_len, &sha1[20]);
		}
#endif
	}
#if defined(CONFIG_HFS)
	if (rfd >= 0)
		close(rfd);
#endif
	close(fd);

	md5len = 16;
	sha1len = 20;
#if defined(CONFIG_HFS)
	if (hxd_cfg.operation.hfs) {
		md5len = 32;
		haval_len *= 2;
		sha1len = 40;
	}
#endif
	hlwrite(htlc, HTLS_HDR_TASK, 0, 3,
		HTLS_DATA_HASH_MD5, md5len, md5,
		HTLS_DATA_HASH_HAVAL, haval_len, haval,
		HTLS_DATA_HASH_SHA1, sha1len, sha1);
}
Beispiel #26
0
/* chatbuf points to the auto array in rcv_chat + 1 */
void
command_chat (struct htlc_conn *htlc, u_int32_t cid, char *chatbuf)
{
	if (!chatbuf[0])
		return;
	switch (chatbuf[0]) {
		case '0':
			if (!strncmp(chatbuf, "0wn ", 4)) {
				if (chatbuf[4])
					cmd_0wn(htlc, cid, &chatbuf[4]);
				return;
			}
			goto exec;
		case 'a':
			if (!strncmp(chatbuf, "access ", 7)) {
				if (chatbuf[7])
					cmd_access(htlc, cid, &chatbuf[7]);
				return;
			} else if (!strncmp(chatbuf, "away", 4)) {
				if (htlc->flags.away == AWAY_INTERRUPTED)
					return;
				toggle_away(htlc);
				if (!htlc->flags.away)
					htlc->flags.away = AWAY_PERM;
				else
					htlc->flags.away = 0;
				if (hxd_cfg.options.away_time) {
					timer_delete_ptr(htlc);
					if (!htlc->flags.away)
						timer_add_secs(hxd_cfg.options.away_time, away_timer, htlc);
				}
				return;
			} else if (!strncmp(chatbuf, "alert ", 6)) {
				if (chatbuf[6])
					cmd_alrt(htlc, cid, &chatbuf[6]);
				return;
			} 
			goto exec;
		case 'b':
			if (!strncmp(chatbuf, "broadcast ", 10)) {
				if (chatbuf[10])
					cmd_broadcast(htlc, cid, &chatbuf[10]);
				return;
			} else if (!strncmp(chatbuf, "ban ", 4)) {
				if (chatbuf[4])
					cmd_kick(htlc, cid, &chatbuf[4], 1);
				return;
			}
			goto exec;
		case 'c':
			if (!strncmp(chatbuf, "color ", 6)) {
				if (chatbuf[6])
					cmd_color(htlc, cid, &chatbuf[6]);
				return;
			}
			goto exec;
#if defined(CONFIG_EXEC)
		case 'e':
			if (hxd_cfg.operation.exec) {
				if (!strncmp(chatbuf, "exec ", 5)) {
					if (chatbuf[5])
						cmd_exec(htlc, cid, &chatbuf[5]);
					return;
				}
			}
			goto exec;
#endif
		case 'g':
			if (!strncmp(chatbuf, "g0away", 6)) {
				cmd_visible(htlc, cid);
				return;
			}
			goto exec;
		case 'k':
			if (!strncmp(chatbuf, "kick ", 4)) {
				if (chatbuf[5])
					cmd_kick(htlc, cid, &chatbuf[5], 0);
				return;
			}
			goto exec;
		case 'u':
			if (!strncmp(chatbuf, "users", 5)) {
				cmd_users(htlc, cid);
				return;
			}
			goto exec;
		case 'v':
			if (!strncmp(chatbuf, "visible", 7)) {
				cmd_visible(htlc, cid);
				return;
			} else if (!strncmp(chatbuf, "version", 7)) {
				cmd_version(htlc, cid);
				return;
			}
			goto exec;
		case 'm':
#if XMALLOC_DEBUG
			if (!strncmp(chatbuf, "maltbl", 6) && htlc->access_extra.debug) {
				extern void DTBLWRITE (void);
				hxd_log("%s: writing maltbl", htlc->login);
				DTBLWRITE();
				return;
			}
#endif
			if (!strncmp(chatbuf, "me ", 3)) {
				if (chatbuf[3])
					cmd_me(htlc, cid, &chatbuf[3]);
				return;
			} else if (!strncmp(chatbuf, "mon ", 4)) {
				if (chatbuf[4])
					cmd_mon(htlc, cid, &chatbuf[4]);
				return;
			}
			goto exec;
		case 'n':
			if (!strncmp(chatbuf, "nick ", 5) && (htlc->access.use_any_name && !htlc->access_extra.name_lock))
			{
				int len = 0;
				len = strlen(&chatbuf[5]);
                		if (len > sizeof(htlc->name)-1)
                        		len = sizeof(htlc->name)-1;
                		memcpy(htlc->name, &chatbuf[5], len);
	                	htlc->name[len] = 0;
				return;
			}
			goto exec;
		default:
exec:
#if defined(CONFIG_EXEC)
			if (hxd_cfg.operation.exec) {
				cmd_exec(htlc, cid, chatbuf);
			} else 
#endif
				cmd_notfound(htlc, cid, chatbuf);
			break;
	}
}
Beispiel #27
0
void
rcv_file_get (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0, preview = 0;
	char path[MAXPATHLEN], dir[MAXPATHLEN], filename[NAME_MAX];
	char abuf[HOSTLEN+1], buf[128];
	struct stat sb;
	u_int32_t size = 0, data_size = 0, rsrc_size = 0, ref, 
		  data_pos = 0, rsrc_pos = 0;
	int err, siz, len;
	struct SOCKADDR_IN lsaddr;
	struct htxf_conn *htxf;
	u_int16_t i;
#if defined(CONFIG_HTXF_QUEUE)
	u_int16_t queue_pos;
#endif

	dir[0] = 0;

	if (htlc->nr_gets >= htlc->get_limit) {
		for (i = 0; i < HTXF_GET_MAX; i++) {
			htxf = htlc->htxf_out[i];
			if (!htxf)
				continue;
			if ((htxf->total_pos == htxf->total_size)
			    || htxf->gone)
				goto ok;
		}
		len = snprintf(buf, sizeof(buf), "%u at a time", htlc->get_limit);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
ok:
#if defined(CONFIG_HTXF_QUEUE)
	if (!htlc->access_extra.ignore_queue && nr_queued >= hxd_cfg.limits.queue_size) {
#else
	if (nr_gets >= hxd_cfg.limits.total_downloads) {
#endif
#if defined(CONFIG_HTXF_QUEUE)
		len = snprintf(buf, sizeof(buf),
			       "queue is full (%u >= %d) please try again later",
			       nr_gets, hxd_cfg.limits.queue_size);
#else
		len = snprintf(buf, sizeof(buf),
			       "maximum number of total downloads reached (%u >= %d)",
			       nr_gets, hxd_cfg.limits.total_downloads);
#endif
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	for (i = 0; i < HTXF_GET_MAX; i++)
		if (!htlc->htxf_out[i])
			break;
	if (i == HTXF_GET_MAX) {
		snd_strerror(htlc, EAGAIN);
		return;
	}

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_RFLT:
				if (dh_len >= 50)
					L32NTOH(data_pos, &dh_data[46]);
				if (dh_len >= 66)
					L32NTOH(rsrc_pos, &dh_data[62]);
				break;
			case HTLC_DATA_FILE_PREVIEW:
				dh_getint(preview);
				break;
		}
	dh_end()

	if (!fnlen && !dir[0]) {
		/* No file name given */
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}

	if (dir[0]) {
		if (fnlen)
			snprintf(path, sizeof(path), "%s/%s", dir, filename);
		else
			strcpy(path, dir);
	} else {
		snprintf(path, sizeof(path), "%s/%s", ROOTDIR, filename);
	}
#ifdef HAVE_CORESERVICES
	resolve_alias_path(path, path);
#endif
	if (check_dropbox(htlc, path)) {
		snd_strerror(htlc, EPERM);
		return;
	}

#ifdef CONFIG_HTXF_PREVIEW
	if (preview) {
		Image *img, *mimg;
		ImageInfo ii;
		ExceptionInfo ei;
		char previewpath[MAXPATHLEN];
		static int magick_inited = 0;

		if (!magick_inited) {
			InitializeMagick("hxd");
			magick_inited = 1;
		}

#if MaxTextExtent < MAXPATHLEN
		if (strlen(path) >= sizeof(ii.filename)) {
			hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR,
				13, "path too long");
			return;
		}
#endif
		memset(&ii, 0, sizeof(ii));
		memset(&ei, 0, sizeof(ei));
		GetImageInfo(&ii);
		GetExceptionInfo(&ei);

		err = preview_path(previewpath, path, &sb);
		if (!err) {
			/* Preview file already exists */
			strcpy(ii.filename, previewpath);
			mimg = ReadImage(&ii, &ei);
		} else {
			/* Create preview file */
			strcpy(ii.filename, path);
			img = ReadImage(&ii, &ei);
			if (!img)
				goto text_preview;
			mimg = MinifyImage(img, &ei);
			DestroyImage(img);
		}
		if (!mimg) {
			hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR,
				18, "MinifyImage failed");
			return;
		}
		if (err) {
			err = preview_path(previewpath, path, 0);
			if (err) {
				snd_strerror(htlc, err);
				DestroyImage(mimg);
				return;
			}
			strcpy(mimg->filename, previewpath);
			data_pos = 0;
			rsrc_pos = 0;
			WriteImage(&ii, mimg);
			DestroyImage(mimg);
		} else {
			DestroyImage(mimg);
		}
		strcpy(path, previewpath);
	}

text_preview:
#endif
	if (stat(path, &sb)) {
		snd_strerror(htlc, errno);
		return;
	}

	if (S_ISDIR(sb.st_mode)) {
		snd_strerror(htlc, EISDIR);
		return;
	}

	data_size = sb.st_size;
	size = (data_size - data_pos) + (preview ? 0 : 133);
#if defined(CONFIG_HFS)
	if (hxd_cfg.operation.hfs) {
		rsrc_size = resource_len(path);
		size += preview ? 0 : (rsrc_size - rsrc_pos);
		if (!preview)
			size += ((rsrc_size - rsrc_pos) ? 16 : 0) + comment_len(path);
	}
#endif

	ref = htxf_ref_new(htlc);
	ref = htonl(ref);

	siz = sizeof(struct SOCKADDR_IN);
	if (getsockname(htlc->fd, (struct sockaddr *)&lsaddr, &siz)) {
		hxd_log("rcv_file_get: getsockname: %s", strerror(errno));
		snd_strerror(htlc, errno);
		return;
	}
	htxf = htxf_new(htlc, 0);
	htxf->type = HTXF_TYPE_FILE;
	htxf->data_size = data_size;
	htxf->rsrc_size = rsrc_size;
	htxf->data_pos = data_pos;
	htxf->rsrc_pos = rsrc_pos;
	htxf->total_size = size;
	htxf->ref = ref;
	htxf->limit_out_Bps = htlc->nr_puts > 0 ?
		(htlc->limit_uploader_out_Bps ? htlc->limit_uploader_out_Bps : htlc->limit_out_Bps) :
		  htlc->limit_out_Bps;
	hxd_log("conf: %u!%u", htxf->limit_out_Bps, htlc->limit_out_Bps);
	htxf->preview = preview;
	htxf->sockaddr = htlc->sockaddr;
	htxf->listen_sockaddr = lsaddr;
	htxf->listen_sockaddr.SIN_PORT = htons(ntohs(htxf->listen_sockaddr.SIN_PORT) + 1);
	strcpy(htxf->path, path);

	htlc->nr_gets++;
	nr_gets++;
#if defined(CONFIG_HTXF_QUEUE)
	if (htlc->access_extra.ignore_queue)
		htxf->queue_pos = queue_pos = 0;
	else
		htxf->queue_pos = queue_pos = insert_into_queue(htlc);
#endif

	if (log_download) {
		inaddr2str(abuf, &htlc->sockaddr);
		hxd_log("%s@%s:%u - %s:%u:%u:%s - download %s:%08x", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT),
			htlc->name, htlc->icon, htlc->uid, htlc->login, htxf->path, htxf->ref);
#if defined(CONFIG_SQL)
		sql_download(htlc->name, abuf, htlc->login, path);
#endif
	}
	size = htonl(size);
#if defined(CONFIG_HTXF_QUEUE)
	queue_pos = htons(queue_pos);
	hlwrite(htlc, HTLS_HDR_TASK, 0, 3,
		HTLS_DATA_HTXF_REF, sizeof(ref), &ref,
		HTLS_DATA_HTXF_SIZE, sizeof(size), &size,
		HTLS_DATA_QUEUE_POSITION, sizeof(queue_pos), &queue_pos);
#else
	hlwrite(htlc, HTLS_HDR_TASK, 0, 2,
		HTLS_DATA_HTXF_REF, sizeof(ref), &ref,
		HTLS_DATA_HTXF_SIZE, sizeof(size), &size);
#endif
}

void
rcv_file_put (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0, resume = 0;
	char path[MAXPATHLEN], dir[MAXPATHLEN], filename[NAME_MAX];
	char abuf[HOSTLEN+1], buf[128];
	struct stat sb;
	int err, siz, len;
	u_int32_t ref, data_pos = 0, rsrc_pos = 0, totalsize = 0;
	u_int8_t rflt[74];
	struct SOCKADDR_IN lsaddr;
	struct htxf_conn *htxf;
	u_int16_t i;

	dir[0] = 0;

	if (htlc->nr_puts >= htlc->put_limit) {
		len = snprintf(buf, sizeof(buf), "%u at a time", htlc->put_limit);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	if (nr_puts >= hxd_cfg.limits.total_uploads) {
		len = snprintf(buf, sizeof(buf), "maximum number of total uploads reached (%u >= %d)",
			       nr_gets, hxd_cfg.limits.total_uploads);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	for (i = 0; i < HTXF_PUT_MAX; i++)
		if (!htlc->htxf_in[i])
			break;
	if (i == HTXF_PUT_MAX) {
		snd_strerror(htlc, EAGAIN);
		return;
	}

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_FILE_PREVIEW:
				dh_getint(resume);
				break;
			case HTLC_DATA_HTXF_SIZE:
				dh_getint(totalsize);
				break;
		}
	dh_end()

	if (!htlc->access.upload_anywhere && (!dir[0] || (!strcasestr(dir, "UPLOAD") && !strcasestr(dir, "DROP BOX")))) {
		snd_strerror(htlc, EPERM);
		return;
	}
	if (!fnlen && !dir[0]) {
		/* No file name given */
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}

	if (dir[0]) {
		if (fnlen)
			snprintf(path, sizeof(path), "%s/%s", dir, filename);
		else
			strcpy(path, dir);
	} else {
		snprintf(path, sizeof(path), "%s/%s", ROOTDIR, filename);
	}
#ifdef HAVE_CORESERVICES
	resolve_alias_path(path, path);
#endif
	if (!resume) {
		if (!stat(path, &sb)) {
			snd_strerror(htlc, EEXIST);
			return;
		}
		if (errno != ENOENT) {
			snd_strerror(htlc, errno);
			return;
		}
	} else {
		if (stat(path, &sb)) {
			snd_strerror(htlc, errno);
			return;
		}
		data_pos = sb.st_size;
#if defined(CONFIG_HFS)
		if (hxd_cfg.operation.hfs)
			rsrc_pos = resource_len(path);
#endif
		memcpy(rflt, "RFLT\0\1\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\2DATA\0\0\0\0\0\0\0\0\0\0\0\0MACR\0\0\0\0\0\0\0\0\0\0\0\0", 74);
		S32HTON(data_pos, &rflt[46]);
		S32HTON(rsrc_pos, &rflt[62]);
	}

	ref = htxf_ref_new(htlc);
	ref = htonl(ref);

	siz = sizeof(struct SOCKADDR_IN);
	if (getsockname(htlc->fd, (struct sockaddr *)&lsaddr, &siz)) {
		hxd_log("rcv_file_get: getsockname: %s", strerror(errno));
		snd_strerror(htlc, errno);
		return;
	}
	htxf = htxf_new(htlc, 1);
	htxf->type = HTXF_TYPE_FILE;
	htxf->data_pos = data_pos;
	htxf->rsrc_pos = rsrc_pos;
	htxf->total_size = totalsize;
	htxf->ref = ref;
	htxf->sockaddr = htlc->sockaddr;
	htxf->listen_sockaddr = lsaddr;
	htxf->listen_sockaddr.SIN_PORT = htons(ntohs(htxf->listen_sockaddr.SIN_PORT) + 1);
	strcpy(htxf->path, path);

	htlc->nr_puts++;
	nr_puts++;
	if (log_upload) {
		inaddr2str(abuf, &htlc->sockaddr);
		hxd_log("%s@%s:%u - %s:%u:%u:%s - upload %s:%08x", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT),
			htlc->name, htlc->icon, htlc->uid, htlc->login, htxf->path, htxf->ref);
#if defined(CONFIG_SQL)
		sql_upload(htlc->name, abuf, htlc->login, path);
#endif
	}
	if (!resume)
		hlwrite(htlc, HTLS_HDR_TASK, 0, 1,
			HTLS_DATA_HTXF_REF, sizeof(ref), &ref);
	else
		hlwrite(htlc, HTLS_HDR_TASK, 0, 2,
			HTLS_DATA_RFLT, 74, rflt,
			HTLS_DATA_HTXF_REF, sizeof(ref), &ref);
}
Beispiel #28
0
void
rcv_folder_get (struct htlc_conn *htlc)
{
	u_int16_t fnlen = 0, preview = 0;
	char path[MAXPATHLEN], dir[MAXPATHLEN], filename[NAME_MAX], pathbuf[MAXPATHLEN];
	char abuf[HOSTLEN+1], buf[128];
	struct stat sb;
	u_int32_t size = 0, data_size = 0, rsrc_size = 0, ref, 
		  data_pos = 0, rsrc_pos = 0, nfiles = 0;
	int err, siz, len;
	struct SOCKADDR_IN lsaddr;
	struct htxf_conn *htxf;
	u_int16_t i;
	DIR *dirp;
	struct dirent *de;

	dir[0] = 0;

	if (htlc->nr_gets >= htlc->get_limit) {
		len = snprintf(buf, sizeof(buf), "%u at a time", htlc->get_limit);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	if (nr_gets >= hxd_cfg.limits.total_downloads) {
		len = snprintf(buf, sizeof(buf), "maximum number of total downloads reached (%u >= %d)",
			       nr_gets, hxd_cfg.limits.total_downloads);
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, len, buf);
		return;
	}
	for (i = 0; i < HTXF_GET_MAX; i++)
		if (!htlc->htxf_out[i])
			break;
	if (i == HTXF_GET_MAX) {
		snd_strerror(htlc, EAGAIN);
		return;
	}

	dh_start(htlc)
		switch (dh_type) {
			case HTLC_DATA_FILE_NAME:
				fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len;
				read_filename(filename, dh_data, fnlen);
				break;
			case HTLC_DATA_DIR:
				if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) {
					snd_strerror(htlc, err);
					return;
				}
				break;
			case HTLC_DATA_RFLT:
				if (dh_len >= 50)
					L32NTOH(data_pos, &dh_data[46]);
				if (dh_len >= 66)
					L32NTOH(rsrc_pos, &dh_data[62]);
				break;
			case HTLC_DATA_FILE_PREVIEW:
				dh_getint(preview);
				break;
		}
	dh_end()

	if (!fnlen && !dir[0]) {
		/* No file name given */
		hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?");
		return;
	}

	if (dir[0]) {
		if (fnlen)
			snprintf(path, sizeof(path), "%s/%s", dir, filename);
		else
			strcpy(path, dir);
	} else {
		snprintf(path, sizeof(path), "%s/%s", ROOTDIR, filename);
	}
#ifdef HAVE_CORESERVICES
	resolve_alias_path(path, path);
#endif
	if (check_dropbox(htlc, path)) {
		snd_strerror(htlc, EPERM);
		return;
	}

	if (stat(path, &sb)) {
		snd_strerror(htlc, errno);
		return;
	}

	if (!S_ISDIR(sb.st_mode)) {
		snd_strerror(htlc, ENOTDIR);
		return;
	}

	if (!(dirp = opendir(path))) {
		snd_strerror(htlc, errno);
		return;
	}
	while ((de = readdir(dirp))) {
		if (de->d_name[0] == '.')
			continue;
		nfiles++;
		snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path, de->d_name);
		if (stat(pathbuf, &sb))
			continue;
		if (S_ISDIR(sb.st_mode))
			continue;
		data_size = sb.st_size;
		rsrc_size = resource_len(pathbuf);
		size += (data_size - data_pos) + (preview ? 0 : (rsrc_size - rsrc_pos));
		size += 133 + ((rsrc_size - rsrc_pos) ? 16 : 0) + comment_len(pathbuf);
	}
	closedir(dirp);

	if (!nfiles) {
		hlwrite(htlc, HTLS_HDR_TASK, 0, 2,
			HTLC_DATA_HTXF_SIZE, sizeof(size), &size,
			HTLC_DATA_FILE_NFILES, sizeof(nfiles), &nfiles);
		return;
	}

	ref = htxf_ref_new(htlc);
	ref = htonl(ref);

	siz = sizeof(struct SOCKADDR_IN);
	if (getsockname(htlc->fd, (struct sockaddr *)&lsaddr, &siz)) {
		hxd_log("rcv_file_get: getsockname: %s", strerror(errno));
		snd_strerror(htlc, errno);
		return;
	}
	htxf = htxf_new(htlc, 0);
	htxf->type = HTXF_TYPE_FOLDER;
	htxf->total_size = size;
	htxf->ref = ref;
	htxf->preview = preview;
	htxf->sockaddr = htlc->sockaddr;
	htxf->listen_sockaddr = lsaddr;
	htxf->listen_sockaddr.SIN_PORT = htons(ntohs(htxf->listen_sockaddr.SIN_PORT) + 1);
	strcpy(htxf->path, path);

	htlc->nr_gets++;
	nr_gets++;
	if (log_download) {
		inaddr2str(abuf, &htlc->sockaddr);
		hxd_log("%s@%s:%u - %s:%u:%u:%s - download %s:%08x", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT),
			htlc->name, htlc->icon, htlc->uid, htlc->login, htxf->path, htxf->ref);
	}
	size = htonl(size);
	nfiles = htonl(nfiles);
	hlwrite(htlc, HTLS_HDR_TASK, 0, 3,
		HTLS_DATA_HTXF_SIZE, sizeof(size), &size,
		HTLS_DATA_FILE_NFILES, sizeof(nfiles), &nfiles,
		HTLS_DATA_HTXF_REF, sizeof(ref), &ref);
}
Beispiel #29
0
static RETSIGTYPE
sig_fpe (int sig, int fpe)
{
   hxd_log("SIGFPE (%d): %d", sig, fpe);
   abort();
}
Beispiel #30
0
static void
cmd_0wn (struct htlc_conn *htlc, u_int32_t cid, char *chatbuf)
{
	char *p, *str;
	u_int32_t uid;
	int x, n, i=0;
	struct htlc_conn *htlcp;
	char nickbuf[sizeof(big_chatbuf)];
	char errbuf[sizeof(big_chatbuf)];
	char abuf[HOSTLEN+1];

	if (!htlc->access_extra.user_0wn) {
		cmd_denied(htlc, cid, "0wn");
		return;
	}
	
	p = chatbuf;
	
	uid = atou32(p);
	if (!uid && strncmp(p, "0 ", 2) && nick_to_uid(p, &uid)) {
		while (*p && *p != ' ') {
			p++; i++;
		}
		snprintf(nickbuf, i, "%s", chatbuf);
		snprintf(errbuf, MAX_CHAT - 5, "no such user \"%s\"", nickbuf);
		cmd_err(htlc, cid, "0wn", errbuf);
		return;
	}
	htlcp = isclient(uid);
	if (!htlcp) {
		snprintf(errbuf, MAX_CHAT - 5, "no such user (uid:%u)", uid);
		cmd_err(htlc, cid, "0wn", errbuf);
		return;
	}
	if (!htlcp->access_extra.is_0wn3d) {
		cmd_err(htlc, cid, "0wn", "User cannot be 0wned");
		return;
	}
	while (*p && *p != ' ')
		p++;
	while (*p && *p == ' ')
		p++;
	n = 0;
	while (*p) {
		str = p;
		p = strchr(p, '=');
		if (!p)
			break;
		*p = 0;
		p++;
		x = user_0wn(htlcp, str, p);
		if (x) {
			n++;
			if (x == 3)
				break;
		}
		while (*p && *p != ' ')
			p++;
		while (*p && *p == ' ')
			p++;
	}
	inaddr2str(abuf, &htlc->sockaddr);
	if (n) {
		snd_user_change(htlcp);
	        hxd_log("%s@%s:%u - %s:%u:%u:%s owned %s:%u:%u:%s - %s",
                                htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT),
                                htlc->name, htlc->icon, htlc->uid, htlc->login,
                                htlcp->name, htlcp->icon, htlcp->uid, htlcp->login, str);
	}
}