Example #1
0
BOOL trim_string_w(smb_ucs2_t *s, const smb_ucs2_t *front,
				  const smb_ucs2_t *back)
{
	BOOL ret = False;
	size_t len, front_len, back_len;

	if (!s) {
		return False;
	}

	len = strlen_w(s);

	if (front && *front) {
		front_len = strlen_w(front);
		while (len && strncmp_w(s, front, front_len) == 0) {
			memmove(s, (s + front_len), (len - front_len + 1) * sizeof(smb_ucs2_t));
			len -= front_len;
			ret = True;
		}
	}
	
	if (back && *back) {
		back_len = strlen_w(back);
		while (len && strncmp_w((s + (len - back_len)), back, back_len) == 0) {
			s[len - back_len] = 0;
			len -= back_len;
			ret = True;
		}
	}

	return ret;
}
Example #2
0
static int run_list(struct asfd *asfd,
	struct sdirs *sdirs, struct conf **cconfs)
{
	int ret=-1;
	char *cp=NULL;
	char *backupno=NULL;
	char *browsedir=NULL;
	char *listregex=NULL;
	struct iobuf *rbuf=asfd->rbuf;

	if(!client_can_generic(cconfs, OPT_CLIENT_CAN_LIST))
	{
		logp("Not allowing list of %s\n",
			get_string(cconfs[OPT_CNAME]));
		asfd->write_str(asfd, CMD_GEN, "Client list is not allowed");
		goto end;
	}

	if(!strncmp_w(rbuf->buf, "list "))
	{
		if((cp=strchr(rbuf->buf, ':')))
		{
			*cp='\0';
			if(!(listregex=strdup_w(cp+1, __func__)))
				goto end;
		}
		if(!(backupno=strdup_w(rbuf->buf+strlen("list "), __func__)))
			goto end;
		
	}
	else if(!strncmp_w(rbuf->buf, "listb "))
	{
		if((cp=strchr(rbuf->buf, ':')))
		{
			*cp='\0';
			if(!(browsedir=strdup_w(cp+1, __func__)))
				goto end;
		}
		strip_trailing_slashes(&browsedir);
		if(!(backupno=strdup_w(rbuf->buf+strlen("listb "), __func__)))
			goto end;
	}
	if(asfd->write_str(asfd, CMD_GEN, "ok")) goto end;

	iobuf_free_content(asfd->rbuf);

	if(list_server_init(asfd, sdirs, get_cntr(cconfs),
		get_protocol(cconfs), backupno, listregex, browsedir))
			goto end;
	ret=do_list_server();
end:
	free_w(&backupno);
	free_w(&browsedir);
	free_w(&listregex);
	list_server_free();
	return ret;
}
Example #3
0
File: main.c Project: jkniiv/burp
static enum cliret maybe_check_timer(struct asfd *asfd,
	enum action action, const char *phase1str,
	struct conf *conf, int *resume)
{
	int complen=0;
	struct iobuf *rbuf=asfd->rbuf;

        if(asfd->write_str(asfd, CMD_GEN, phase1str)) goto error;

        if(asfd->read(asfd)) goto error;

        if(rbuf->cmd!=CMD_GEN)
        {
		iobuf_free_content(rbuf);
		iobuf_log_unexpected(rbuf, __func__);
		goto error;
        }
        if(!strcmp(rbuf->buf, "timer conditions not met"))
        {
		iobuf_free_content(rbuf);
                logp("Timer conditions on the server were not met\n");
		goto timer_not_met;
        }
        else if(!strcmp(rbuf->buf, "timer conditions met"))
        {
		iobuf_free_content(rbuf);
                logp("Timer conditions on the server were met\n");
		if(action==ACTION_TIMER_CHECK) goto end;
        }

	if(!strncmp_w(rbuf->buf, "ok"))
		complen=3;
	else if(!strncmp_w(rbuf->buf, "resume"))
	{
		complen=7;
		*resume=1;
		logp("server wants to resume previous backup.\n");
	}
	else
	{
		iobuf_log_unexpected(rbuf, __func__);
		iobuf_free_content(rbuf);
		goto error;
	}
        // The server now tells us the compression level in the OK response.
        if(strlen(rbuf->buf)>3) conf->compression=atoi(rbuf->buf+complen);
        logp("Compression level: %d\n", conf->compression);

	iobuf_free_content(rbuf);
end:
	return CLIENT_OK;
error:
	return CLIENT_ERROR;
timer_not_met:
	return CLIENT_SERVER_TIMER_NOT_MET;
}
Example #4
0
static const char *buf_to_notify_str(struct iobuf *rbuf)
{
	const char *buf=rbuf->buf;
	if(!strncmp_w(buf, "backup")) return "backup";
	else if(!strncmp_w(buf, "restore")) return "restore";
	else if(!strncmp_w(buf, "verify")) return "verify";
	else if(!strncmp_w(buf, "delete")) return "delete";
	else if(!strncmp_w(buf, "list")) return "list";
	else return "unknown";
}
Example #5
0
static int deal_with_client_rbuf(struct asfd *asfd, const char *directory,
	struct scores *scores)
{
	if(asfd->rbuf->cmd==CMD_GEN)
	{
		if(!strncmp_w(asfd->rbuf->buf, "cname:"))
		{
			struct iobuf wbuf;
			free_w(&asfd->desc);
			if(!(asfd->desc=strdup_w(asfd->rbuf->buf
				+strlen("cname:"), __func__)))
					goto error;
			logp("%s: fd %d\n", asfd->desc, asfd->fd);
			iobuf_set(&wbuf, CMD_GEN,
				(char *)"cname ok", strlen("cname ok"));

			if(asfd->write(asfd, &wbuf))
				goto error;
		}
		else if(!strncmp_w(asfd->rbuf->buf, "sigs_end"))
		{
			//printf("Was told no more sigs\n");
			if(deduplicate(asfd, directory, scores)<0)
				goto error;
		}
		else
		{
			iobuf_log_unexpected(asfd->rbuf, __func__);
			goto error;
		}
	}
	else if(asfd->rbuf->cmd==CMD_SIG)
	{
		if(champ_server_deal_with_rbuf_sig(asfd, directory, scores))
			goto error;
	}
	else if(asfd->rbuf->cmd==CMD_MANIFEST)
	{
		// Client has completed a manifest file. Want to start using
		// it as a dedup candidate now.
		if(candidate_add_fresh(asfd->rbuf->buf, directory, scores))
			goto error;
	}
	else
	{
		iobuf_log_unexpected(asfd->rbuf, __func__);
		goto error;
	}
	iobuf_free_content(asfd->rbuf);
	return 0;
error:
	iobuf_free_content(asfd->rbuf);
	return -1;
}
Example #6
0
static int parse_restore_str(const char *str, enum action *act,
	char **backupnostr, char **restoreregex)
{
	int ret=-1;
	char *cp=NULL;
	char *copy=NULL;

	if(!str)
	{
		logp("NULL passed to %s\n", __func__);
		goto end;
	}

	if(!(copy=strdup_w(str, __func__)))
		goto end;

	if(!strncmp_w(copy, "restore "))
		*act=ACTION_RESTORE;
	else if(!strncmp_w(copy, "verify "))
		*act=ACTION_VERIFY;
	else
	{
		logp("Could not parse %s in %s\n", copy, __func__);
		goto end;
	}

	if(!(cp=strchr(copy, ' ')))
	{
		logp("Could not parse %s in %s\n", copy, __func__);
		goto end;
	}
	cp++;
	if(!(*backupnostr=strdup_w(cp, __func__)))
		goto end;
	if((cp=strchr(*backupnostr, ':')))
	{
		*cp='\0';
		cp++;
		if(!(*restoreregex=strdup_w(cp, __func__)))
			goto end;
	}

	ret=0;
end:
	free_w(&copy);
	return ret;
}
Example #7
0
static int srestore_matches(struct strlist *s, const char *path)
{
	int r=0;
	if(!s->flag) return 0; // Do not know how to do excludes yet.
	if((r=strncmp_w(path, s->path))) return 0; // no match
	if(!r) return 1; // exact match
	if(*(path+strlen(s->path)+1)=='/')
		return 1; // matched directory contents
	return 0; // no match
}
Example #8
0
File: main.c Project: scosu/burp
static enum asl_ret maybe_check_timer_func(struct asfd *asfd,
	struct conf **confs, void *param)
{
	int complen=0;
	struct tchk *tchk=(struct tchk *)param;

	if(!strcmp(asfd->rbuf->buf, "timer conditions not met"))
	{
		logp("Timer conditions on the server were not met\n");
		tchk->ret=CLIENT_SERVER_TIMER_NOT_MET;
		return ASL_END_OK;
	}
	else if(!strcmp(asfd->rbuf->buf, "timer conditions met"))
	{
		// Only happens on 'timer check only'.
		logp("Timer conditions on the server were met\n");
		tchk->ret=CLIENT_OK;
		return ASL_END_OK;
	}

	if(!strncmp_w(asfd->rbuf->buf, "ok"))
		complen=3;
	else if(!strncmp_w(asfd->rbuf->buf, "resume"))
	{
		complen=7;
		tchk->resume=1;
		logp("server wants to resume previous backup.\n");
	}
	else
	{
		iobuf_log_unexpected(asfd->rbuf, __func__);
		return ASL_END_ERROR;
	}

	// The server now tells us the compression level in the OK response.
	if(strlen(asfd->rbuf->buf)>3)
		set_int(confs[OPT_COMPRESSION], atoi(asfd->rbuf->buf+complen));
	logp("Compression level: %d\n",
		get_int(confs[OPT_COMPRESSION]));

	return ASL_END_OK;
}
Example #9
0
smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins)
{
	smb_ucs2_t *r;
	size_t slen, inslen;

	if (!s || !*s || !ins || !*ins) return NULL;
	slen = strlen_w(s);
	inslen = strlen_w(ins);
	r = (smb_ucs2_t *)s;
	while ((r = strchr_w(r, *ins))) {
		if (strncmp_w(r, ins, inslen) == 0) return r;
		r++;
	}
	return NULL;
}
Example #10
0
static int parse_action(enum action *act, const char *optarg)
{
	if(!strncmp(optarg, "backup", 1))
		*act=ACTION_BACKUP;
	else if(!strncmp(optarg, "timedbackup", 1))
		*act=ACTION_BACKUP_TIMED;
	else if(!strncmp(optarg, "Timercheck", 1))
		*act=ACTION_TIMER_CHECK;
	else if(!strncmp(optarg, "restore", 1))
		*act=ACTION_RESTORE;
	else if(!strncmp(optarg, "verify", 1))
		*act=ACTION_VERIFY;
	else if(!strncmp(optarg, "list", 1))
		*act=ACTION_LIST;
	else if(!strncmp(optarg, "List", 1))
		*act=ACTION_LIST_LONG;
	else if(!strncmp(optarg, "status", 1))
		*act=ACTION_STATUS;
	else if(!strncmp(optarg, "Status", 1))
		*act=ACTION_STATUS_SNAPSHOT;
	else if(!strncmp(optarg, "estimate", 1))
		*act=ACTION_ESTIMATE;
	// Make them spell 'delete' out fully so that it is less likely to be
	// used accidently.
	else if(!strncmp_w(optarg, "delete"))
		*act=ACTION_DELETE;
	else if(!strncmp(optarg, "champchooser", 1))
		*act=ACTION_CHAMP_CHOOSER;
	else if(!strncmp(optarg, "diff", 1))
		*act=ACTION_DIFF;
	else if(!strncmp(optarg, "Diff", 1))
		*act=ACTION_DIFF_LONG;
	else if(!strncmp(optarg, "monitor", 1))
		*act=ACTION_MONITOR;
	else
	{
		usage();
		return -1;
	}
	return 0;
}
Example #11
0
smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins)
{
	const smb_ucs2_t *r;
	size_t inslen;

	if (!s || !*s || !ins || !*ins) {
		return NULL;
	}

	inslen = strlen_w(ins);
	r = s;

	while ((r = strchr_w(r, *ins))) {
		if (strncmp_w(r, ins, inslen) == 0) {
			return discard_const_p(smb_ucs2_t, r);
		}
		r++;
	}

	return NULL;
}
Example #12
0
static int run_diff(struct asfd *asfd,
	struct sdirs *sdirs, struct conf **cconfs)
{
	int ret=-1;
	char *backup1=NULL;
	char *backup2=NULL;
	struct iobuf *rbuf=asfd->rbuf;

	if(!client_can_generic(cconfs, OPT_CLIENT_CAN_DIFF))
	{
		logp("Not allowing diff of %s\n",
			get_string(cconfs[OPT_CNAME]));
		asfd->write_str(asfd, CMD_GEN, "Client diff is not allowed");
		goto end;
	}

	if(!strncmp_w(rbuf->buf, "diff "))
	{
		char *cp;
		if((cp=strchr(rbuf->buf, ':')))
		{
			*cp='\0';
			if(!(backup2=strdup_w(cp+1, __func__)))
				goto end;
		}
		if(!(backup1=strdup_w(rbuf->buf+strlen("diff "), __func__)))
			goto end;
	}
	if(asfd->write_str(asfd, CMD_GEN, "ok")) goto end;

	iobuf_free_content(asfd->rbuf);

	ret=do_diff_server(asfd, sdirs,
		get_cntr(cconfs), get_protocol(cconfs), backup1, backup2);
end:
	return ret;
}
Example #13
0
static enum asl_ret restore_spool_func(struct asfd *asfd,
	struct conf **confs, void *param)
{
	static char **datpath;
	static struct iobuf *rbuf;
	datpath=(char **)param;
	rbuf=asfd->rbuf;
	if(!strncmp_w(rbuf->buf, "dat="))
	{
		char *fpath=NULL;
		if(!(fpath=prepend_s(*datpath, rbuf->buf+4))
		  || build_path_w(fpath)
		  || receive_a_file(asfd, fpath, get_cntr(confs)))
			return ASL_END_ERROR;
		iobuf_free_content(rbuf);
	}
	else if(!strcmp(rbuf->buf, "datfilesend"))
	{
		if(asfd->write_str(asfd, CMD_GEN, "datfilesend_ok"))
			return ASL_END_ERROR;
		return ASL_END_OK;
	}
	return ASL_CONTINUE;
}
Example #14
0
int authorise_server(struct asfd *asfd,
	struct conf **globalcs, struct conf **cconfs)
{
	int ret=-1;
	char *cp=NULL;
	char *password=NULL;
	char *cname=NULL;
	char whoareyou[256]="";
	struct iobuf *rbuf=asfd->rbuf;
	const char *peer_version=NULL;
	if(asfd->read(asfd))
	{
		logp("unable to read initial message\n");
		goto end;
	}
	if(rbuf->cmd!=CMD_GEN || strncmp_w(rbuf->buf, "hello"))
	{
		iobuf_log_unexpected(rbuf, __func__);
		goto end;
	}
	// String may look like...
	// "hello"
	// "hello:(version)"
	// (version) is a version number
	if((cp=strchr(rbuf->buf, ':')))
	{
		cp++;
		if(cp && set_string(cconfs[OPT_PEER_VERSION], cp))
			goto end;
	}
	iobuf_free_content(rbuf);

	snprintf(whoareyou, sizeof(whoareyou), "whoareyou");
	peer_version=get_string(cconfs[OPT_PEER_VERSION]);
	if(peer_version)
	{
		long min_ver=0;
		long cli_ver=0;
		if((min_ver=version_to_long("1.3.2"))<0
		  || (cli_ver=version_to_long(peer_version))<0)
			return -1;
		// Stick the server version on the end of the whoareyou string.
		// if the client version is recent enough.
		if(min_ver<=cli_ver)
		 snprintf(whoareyou, sizeof(whoareyou),
			"whoareyou:%s", VERSION);
	}

	if(asfd->write_str(asfd, CMD_GEN, whoareyou)
	  || asfd->read(asfd))
	{
		logp("unable to get client name\n");
		goto end;
	}

	if(!(cname=strdup_w(rbuf->buf, __func__)))
		goto end;
	if(!get_int(globalcs[OPT_CNAME_FQDN]))
		strip_fqdn(&cname);
	if(get_int(globalcs[OPT_CNAME_LOWERCASE]))
		strlwr(cname);

	if(set_string(cconfs[OPT_CNAME], cname))
		goto end;
	iobuf_free_content(rbuf);

	if(asfd->write_str(asfd, CMD_GEN, "okpassword")
	  || asfd->read(asfd))
	{
		logp("unable to get password for client %s\n",
			get_string(cconfs[OPT_CNAME]));
		goto end;
	}
	password=rbuf->buf;
	iobuf_init(rbuf);

	if(check_client_and_password(globalcs, password, cconfs))
		goto end;

	if(get_int(cconfs[OPT_VERSION_WARN]))
		version_warn(asfd, globalcs, cconfs);

	logp("auth ok for: %s%s\n", get_string(cconfs[OPT_CNAME]),
		get_int(cconfs[OPT_PASSWORD_CHECK])?
			"":" (no password needed)");

	if(asfd->write_str(asfd, CMD_GEN, "ok"))
		goto end;

	ret=0;
end:
	iobuf_free_content(rbuf);
	free_w(&password);
	free_w(&cname);
	return ret;
}
Example #15
0
File: auth.c Project: Lacoste/burp
int authorise_client(struct asfd *asfd,
	char **server_version, const char *cname, const char *password,
	struct cntr *cntr)
{
	int ret=-1;
	char hello[256]="";
	struct iobuf *rbuf=asfd->rbuf;

	snprintf(hello, sizeof(hello), "hello:%s", VERSION);
	if(asfd->write_str(asfd, CMD_GEN, hello))
	{
		logp("problem with auth\n");
		goto end;
	}

	if(asfd->read(asfd)
	  || rbuf->cmd!=CMD_GEN
	  || strncmp_w(rbuf->buf, "whoareyou"))
	{
		logp("problem with auth\n");
		goto end;
	}
	if(rbuf->buf)
	{
		char *cp=NULL;
		if((cp=strchr(rbuf->buf, ':')))
		{
			cp++;
			if(cp && !(*server_version=strdup_w(cp, __func__)))
				goto end;
		}
		iobuf_free_content(rbuf);
	}

	if(asfd->write_str(asfd, CMD_GEN, cname)
	  || asfd_read_expect(asfd, CMD_GEN, "okpassword")
	  || asfd->write_str(asfd, CMD_GEN, password)
	  || asfd->read(asfd))
	{
		logp("problem with auth\n");
		goto end;
	}

	if(rbuf->cmd==CMD_WARNING) // special case for the version warning
	{
		//logw(conf->p1cntr, rbuf->buf);
		logp("WARNING: %s\n", rbuf->buf);
		cntr_add(cntr, rbuf->cmd, 0);
		iobuf_free_content(rbuf);
		if(asfd->read(asfd))
		{
			logp("problem with auth\n");
			goto end;
		}
	}
	if(rbuf->cmd==CMD_GEN && !strcmp(rbuf->buf, "ok"))
	{
		// It is OK.
		logp("auth ok\n");
	}
	else
	{
		iobuf_log_unexpected(rbuf, __func__);
		goto end;
	}

	ret=0;
end:
	iobuf_free_content(rbuf);
	return ret;
}
Example #16
0
int run_backup(struct async *as, struct sdirs *sdirs, struct conf **cconfs,
	const char *incexc, int *timer_ret, int resume)
{
	int ret;
	char okstr[32]="";
	struct asfd *asfd=as->asfd;
	struct iobuf *rbuf=asfd->rbuf;
	const char *cname=get_string(cconfs[OPT_CNAME]);

	if(get_string(cconfs[OPT_RESTORE_CLIENT]))
	{
		// This client is not the original client, so a backup might
		// cause all sorts of trouble.
		logp("Not allowing backup of %s\n", cname);
		return asfd->write_str(asfd, CMD_GEN, "Backup is not allowed");
	}

	// Set quality of service bits on backups.
	asfd->set_bulk_packets(asfd);

	if(!strncmp_w(rbuf->buf, "backupphase1timed"))
	{
		int a=0;
		const char *args[12];
		int checkonly=!strncmp_w(rbuf->buf, "backupphase1timedcheck");
		if(checkonly) logp("Client asked for a timer check only.\n");

		args[a++]=get_string(cconfs[OPT_TIMER_SCRIPT]);
		args[a++]=cname;
		args[a++]=sdirs->current;
		args[a++]=sdirs->clients;
		args[a++]="reserved1";
		args[a++]="reserved2";
		args[a++]=NULL;
		if((*timer_ret=run_script(asfd, args,
		  get_strlist(cconfs[OPT_TIMER_ARG]),
		  cconfs,
		  1 /* wait */,
		  1 /* use logp */,
		  0 /* no log_remote */
		))<0)
		{
			logp("Error running timer script for %s\n",
				cname);
			return *timer_ret;
		}
		if(*timer_ret)
		{
			if(!checkonly)
				logp("Not running backup of %s\n",
					cname);
			return asfd->write_str(asfd,
				CMD_GEN, "timer conditions not met");
		}
		if(checkonly)
		{
			logp("Client asked for a timer check only,\n");
			logp("so a backup is not happening right now.\n");
			return asfd->write_str(asfd,
				CMD_GEN, "timer conditions met");
		}
		logp("Running backup of %s\n", cname);
	}
	else if(!get_int(cconfs[OPT_CLIENT_CAN_FORCE_BACKUP]))
	{
		logp("Not allowing forced backup of %s\n", cname);
		return asfd->write_str(asfd,
			CMD_GEN, "Forced backup is not allowed");
	}

	snprintf(okstr, sizeof(okstr), "%s:%d",
		resume?"resume":"ok", get_int(cconfs[OPT_COMPRESSION]));
	if(asfd->write_str(asfd, CMD_GEN, okstr)) return -1;

	if((ret=do_backup_server(as, sdirs, cconfs, incexc, resume)))
		goto end;

	if((ret=delete_backups(sdirs, cname,
		get_strlist(cconfs[OPT_KEEP]),
		get_string(cconfs[OPT_MANUAL_DELETE]))))
			goto end;
end:
	return ret;
}
Example #17
0
static int extra_comms_read(struct async *as,
	struct vers *vers, int *srestore,
	char **incexc, struct conf **globalcs, struct conf **cconfs)
{
	int ret=-1;
	struct asfd *asfd;
	struct iobuf *rbuf;
	asfd=as->asfd;
	rbuf=asfd->rbuf;

	while(1)
	{
		iobuf_free_content(rbuf);
		if(asfd->read(asfd)) goto end;

		if(rbuf->cmd!=CMD_GEN)
		{
			iobuf_log_unexpected(rbuf, __func__);
			goto end;
		}

		if(!strcmp(rbuf->buf, "extra_comms_end"))
		{
			if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end ok"))
				goto end;
			break;
		}
		else if(!strncmp_w(rbuf->buf, "autoupgrade:"))
		{
			char *os=NULL;
			const char *autoupgrade_dir=
				get_string(globalcs[OPT_AUTOUPGRADE_DIR]);
			os=rbuf->buf+strlen("autoupgrade:");
			iobuf_free_content(rbuf);
			if(os && *os && autoupgrade_server(as, vers->ser,
				vers->cli, os, get_cntr(globalcs),
				autoupgrade_dir))
					goto end;
		}
		else if(!strcmp(rbuf->buf, "srestore ok"))
		{
			iobuf_free_content(rbuf);
			// Client can accept the restore.
			// Load the restore config, then send it.
			*srestore=1;
			if(conf_parse_incexcs_path(cconfs,
				get_string(cconfs[OPT_RESTORE_PATH]))
			  || incexc_send_server_restore(asfd, cconfs))
				goto end;
			// Do not unlink it here - wait until
			// the client says that it wants to do the
			// restore.
			// Also need to leave it around if the
			// restore is to an alternative client, so
			// that the code below that reloads the config
			// can read it again.
			//unlink(get_string(cconfs[OPT_RESTORE_PATH]));
		}
		else if(!strcmp(rbuf->buf, "srestore not ok"))
		{
			const char *restore_path=get_string(
				cconfs[OPT_RESTORE_PATH]);
			// Client will not accept the restore.
			unlink(restore_path);
			if(set_string(cconfs[OPT_RESTORE_PATH], NULL))
				goto end;
			logp("Client not accepting server initiated restore.\n");
		}
		else if(!strcmp(rbuf->buf, "sincexc ok"))
		{
			// Client can accept incexc conf from the
			// server.
			iobuf_free_content(rbuf);
			if(incexc_send_server(asfd, cconfs)) goto end;
		}
		else if(!strcmp(rbuf->buf, "incexc"))
		{
			// Client is telling server its incexc
			// configuration so that it can better decide
			// what to do on resume.
			iobuf_free_content(rbuf);
			if(incexc_recv_server(asfd, incexc, globalcs)) goto end;
			if(*incexc)
			{
				char *tmp=NULL;
				char comp[32]="";
				snprintf(comp, sizeof(comp),
					"compression = %d\n",
					get_int(cconfs[OPT_COMPRESSION]));
				if(!(tmp=prepend(*incexc, comp)))
					goto end;
				free_w(incexc);
				*incexc=tmp;
			}
		}
		else if(!strcmp(rbuf->buf, "countersok"))
		{
			// Client can accept counters on
			// resume/verify/restore.
			logp("Client supports being sent counters.\n");
			set_int(cconfs[OPT_SEND_CLIENT_CNTR], 1);
		}
		else if(!strncmp_w(rbuf->buf, "uname=")
		  && strlen(rbuf->buf)>strlen("uname="))
		{
			char *uname=rbuf->buf+strlen("uname=");
			if(!strncasecmp("Windows", uname, strlen("Windows")))
				set_int(cconfs[OPT_CLIENT_IS_WINDOWS], 1);
		}
		else if(!strncmp_w(rbuf->buf, "orig_client=")
		  && strlen(rbuf->buf)>strlen("orig_client="))
		{
			if(conf_switch_to_orig_client(globalcs, cconfs,
				rbuf->buf+strlen("orig_client=")))
					goto end;
			// If this started out as a server-initiated
			// restore, need to load the restore file
			// again.
			if(*srestore)
			{
				if(conf_parse_incexcs_path(cconfs,
					get_string(cconfs[OPT_RESTORE_PATH])))
						goto end;
			}
			if(asfd->write_str(asfd, CMD_GEN, "orig_client ok"))
				goto end;
		}
		else if(!strncmp_w(rbuf->buf, "restore_spool="))
		{
			// Client supports temporary spool directory
			// for restores.
			if(set_string(cconfs[OPT_RESTORE_SPOOL],
				rbuf->buf+strlen("restore_spool=")))
					goto end;
		}
		else if(!strncmp_w(rbuf->buf, "protocol="))
		{
			char msg[128]="";
			// Client wants to set protocol.
			enum protocol protocol=get_protocol(cconfs);
			if(protocol!=PROTO_AUTO)
			{
				snprintf(msg, sizeof(msg), "Client is trying to use protocol=%s but server is set to protocol=%d\n", rbuf->buf, protocol);
				log_and_send_oom(asfd, __func__);
				goto end;
			}
			else if(!strcmp(rbuf->buf+strlen("protocol="), "1"))
			{
				set_protocol(cconfs, PROTO_1);
				set_protocol(globalcs, PROTO_1);
			}
			else if(!strcmp(rbuf->buf+strlen("protocol="), "2"))
			{
				set_protocol(cconfs, PROTO_2);
				set_protocol(globalcs, PROTO_2);
			}
			else
			{
				snprintf(msg, sizeof(msg), "Client is trying to use protocol=%s, which is unknown\n", rbuf->buf);
				log_and_send_oom(asfd, __func__);
				goto end;
			}
			logp("Client has set protocol=%d\n",
				(int)get_protocol(cconfs));
		}
		else if(!strncmp_w(rbuf->buf, "rshash=blake2"))
		{
#ifdef RS_DEFAULT_STRONG_LEN
			logp("Client is trying to use librsync hash blake2, but server does not support it.\n");
			goto end;
#else
			set_e_rshash(cconfs[OPT_RSHASH], RSHASH_BLAKE2);
			set_e_rshash(globalcs[OPT_RSHASH], RSHASH_BLAKE2);
#endif
		}
		else if(!strncmp_w(rbuf->buf, "msg"))
		{
			set_int(cconfs[OPT_MESSAGE], 1);
			set_int(globalcs[OPT_MESSAGE], 1);
		}
		else
		{
			iobuf_log_unexpected(rbuf, __func__);
			goto end;
		}
	}

	ret=0;
end:
	iobuf_free_content(rbuf);
	return ret;
}
Example #18
0
int authorise_server(struct asfd *asfd, struct conf *conf, struct conf *cconf)
{
	int ret=-1;
	char *cp=NULL;
	char *password=NULL;
	char whoareyou[256]="";
	struct iobuf *rbuf=asfd->rbuf;
	if(asfd->read(asfd))
	{
		logp("unable to read initial message\n");
		goto end;
	}
	if(rbuf->cmd!=CMD_GEN || strncmp_w(rbuf->buf, "hello"))
	{
		iobuf_log_unexpected(rbuf, __func__);
		goto end;
	}
	// String may look like...
	// "hello"
	// "hello:(version)"
	// (version) is a version number
	if((cp=strchr(rbuf->buf, ':')))
	{
		cp++;
		if(cp && !(cconf->peer_version=strdup_w(cp, __func__)))
			goto end;
	}
	iobuf_free_content(rbuf);

	snprintf(whoareyou, sizeof(whoareyou), "whoareyou");
	if(cconf->peer_version)
	{
		long min_ver=0;
		long cli_ver=0;
		if((min_ver=version_to_long("1.3.2"))<0
		  || (cli_ver=version_to_long(cconf->peer_version))<0)
			return -1;
		// Stick the server version on the end of the whoareyou string.
		// if the client version is recent enough.
		if(min_ver<=cli_ver)
		 snprintf(whoareyou, sizeof(whoareyou),
			"whoareyou:%s", VERSION);
	}

	asfd->write_str(asfd, CMD_GEN, whoareyou);
	if(asfd->read(asfd))
	{
		logp("unable to get client name\n");
		goto end;
	}
	cconf->cname=rbuf->buf;
	iobuf_init(rbuf);

	asfd->write_str(asfd, CMD_GEN, "okpassword");
	if(asfd->read(asfd))
	{
		logp("unable to get password for client %s\n", cconf->cname);
		goto end;
	}
	password=rbuf->buf;
	iobuf_init(rbuf);

	if(check_client_and_password(conf, password, cconf))
		goto end;

	if(cconf->version_warn) version_warn(asfd, conf, cconf);

	logp("auth ok for: %s%s\n", cconf->cname,
		cconf->password_check?"":" (no password needed)");

	asfd->write_str(asfd, CMD_GEN, "ok");

	ret=0;
end:
	iobuf_free_content(rbuf);
	free_w(&password);
	return ret;
}
Example #19
0
static int run_action_server_do(struct async *as, struct sdirs *sdirs,
	const char *incexc, int srestore, int *timer_ret, struct conf **cconfs)
{
	int ret;
	int resume=0;
	char msg[256]="";
	struct iobuf *rbuf=as->asfd->rbuf;

	// Make sure some directories exist.
	if(mkpath(&sdirs->current, sdirs->dedup))
	{
		snprintf(msg, sizeof(msg),
			"could not mkpath %s", sdirs->current);
		log_and_send(as->asfd, msg);
		return -1;
	}

	if(rbuf->cmd!=CMD_GEN) return unknown_command(as->asfd);

	// List and diff should work even while backups are running.
	if(!strncmp_w(rbuf->buf, "list ")
	  || !strncmp_w(rbuf->buf, "listb "))
		return run_list(as->asfd, sdirs, cconfs);

	if(!strncmp_w(rbuf->buf, "diff "))
		return run_diff(as->asfd, sdirs, cconfs);

	switch((ret=get_lock_sdirs(as->asfd, sdirs)))
	{
		case 0: break; // OK.
		case 1: return 1; // Locked out.
		default: // Error.
			maybe_do_notification(as->asfd, ret,
				"", "error in get_lock_sdirs()",
				"", buf_to_notify_str(rbuf), cconfs);
			return -1;
	}

	switch((ret=check_for_rubble(as, sdirs, incexc, &resume, cconfs)))
	{
		case 0: break; // OK.
		case 1: return 1; // Now finalising.
		default: // Error.
			maybe_do_notification(as->asfd, ret,
				"", "error in check_for_rubble()",
				"", buf_to_notify_str(rbuf), cconfs);
			return -1;
	}

	if(!strncmp_w(rbuf->buf, "backup"))
	{
		ret=run_backup(as, sdirs, cconfs, incexc, timer_ret, resume);
		if(*timer_ret<0)
			maybe_do_notification(as->asfd, ret, "",
				"error running timer script",
				"", "backup", cconfs);
		else if(!*timer_ret)
			maybe_do_notification(as->asfd, ret, sdirs->client,
				sdirs->current, "log", "backup", cconfs);
		return ret;
	}

	if(!strncmp_w(rbuf->buf, "restore ")
	  || !strncmp_w(rbuf->buf, "verify "))
		return run_restore(as->asfd, sdirs, cconfs, srestore);

	if(!strncmp_w(rbuf->buf, "Delete "))
		return run_delete(as->asfd, sdirs, cconfs);

	// Old clients will send 'delete', possibly accidentally due to the
	// user trying to use the new diff/long diff options.
	// Stop them from working, just to be safe.
	if(!strncmp_w(rbuf->buf, "delete "))
	{
		logp("old style delete from %s denied\n",
			get_string(cconfs[OPT_CNAME]));
		as->asfd->write_str(as->asfd, CMD_ERROR,
			"old style delete is not supported on this server");
		return -1;
	}

	return unknown_command(as->asfd);
}
Example #20
0
int extra_comms(struct async *as, struct conf **confs,
	enum action *action, char **incexc)
{
	int ret=-1;
	char *feat=NULL;
	struct asfd *asfd;
	struct iobuf *rbuf;
	const char *orig_client=get_string(confs[OPT_ORIG_CLIENT]);
	asfd=as->asfd;
	rbuf=asfd->rbuf;

	if(asfd->write_str(asfd, CMD_GEN, "extra_comms_begin"))
	{
		logp("Problem requesting extra_comms_begin\n");
		goto end;
	}
	// Servers greater than 1.3.0 will list the extra_comms
	// features they support.
	if(asfd->read(asfd))
	{
		logp("Problem reading response to extra_comms_begin\n");
		goto end;
	}
	feat=rbuf->buf;
	if(rbuf->cmd!=CMD_GEN
	  || strncmp_w(feat, "extra_comms_begin ok"))
	{
		iobuf_log_unexpected(rbuf, __func__);
		goto end;
	}
	logp("%s\n", feat);
	iobuf_init(rbuf);

	// Can add extra bits here. The first extra bit is the
	// autoupgrade stuff.
	if(server_supports_autoupgrade(feat)
	  && get_string(confs[OPT_AUTOUPGRADE_DIR])
	  && get_string(confs[OPT_AUTOUPGRADE_OS])
	  && autoupgrade_client(as, confs))
		goto end;

	// :srestore: means that the server wants to do a restore.
	if(server_supports(feat, ":srestore:"))
	{
		if(get_int(confs[OPT_SERVER_CAN_RESTORE]))
		{
			logp("Server is initiating a restore\n");
			if(incexc_recv_client_restore(asfd, incexc, confs))
				goto end;
			if(*incexc)
			{
				if(conf_parse_incexcs_buf(confs, *incexc))
					goto end;
				*action=ACTION_RESTORE;
				log_restore_settings(confs, 1);
			}
		}
		else
		{
			logp("Server wants to initiate a restore\n");
			logp("Client configuration says no\n");
			if(asfd->write_str(asfd, CMD_GEN, "srestore not ok"))
				goto end;
		}
	}

	if(orig_client)
	{
		char str[512]="";
		snprintf(str, sizeof(str), "orig_client=%s", orig_client);
		if(!server_supports(feat, ":orig_client:"))
		{
			logp("Server does not support switching client.\n");
			goto end;
		}
		if(asfd->write_str(asfd, CMD_GEN, str)
		  || asfd->read_expect(asfd, CMD_GEN, "orig_client ok"))
		{
			logp("Problem requesting %s\n", str);
			goto end;
		}
		logp("Switched to client %s\n", orig_client);
	}

	// :sincexc: is for the server giving the client the
	// incexc config.
	if(*action==ACTION_BACKUP
	  || *action==ACTION_BACKUP_TIMED
	  || *action==ACTION_TIMER_CHECK)
	{
		if(!*incexc && server_supports(feat, ":sincexc:"))
		{
			logp("Server is setting includes/excludes.\n");
			if(incexc_recv_client(asfd, incexc, confs))
				goto end;
			if(*incexc && conf_parse_incexcs_buf(confs,
				*incexc)) goto end;
		}
	}

	if(server_supports(feat, ":counters:"))
	{
		if(asfd->write_str(asfd, CMD_GEN, "countersok"))
			goto end;
		set_int(confs[OPT_SEND_CLIENT_CNTR], 1);
	}

	// :incexc: is for the client sending the server the
	// incexc conf so that it better knows what to do on
	// resume.
	if(server_supports(feat, ":incexc:")
	  && incexc_send_client(asfd, confs))
		goto end;

	if(server_supports(feat, ":uname:"))
	{
		const char *clientos=NULL;
#ifdef HAVE_WIN32
#ifdef _WIN64
		clientos="Windows 64bit";
#else
		clientos="Windows 32bit";
#endif
#else
		struct utsname utsname;
		if(!uname(&utsname))
			clientos=(const char *)utsname.sysname;
#endif
		if(clientos)
		{
			char msg[128]="";
			snprintf(msg, sizeof(msg),
				"uname=%s", clientos);
			if(asfd->write_str(asfd, CMD_GEN, msg))
				goto end;
		}
	}

	if(server_supports(feat, ":csetproto:"))
	{
		char msg[128]="";
		// Use protocol2 if no choice has been made on client side.
		if(get_e_protocol(confs[OPT_PROTOCOL])==PROTO_AUTO)
		{
			logp("Server has protocol=0 (auto)\n");
			set_e_protocol(confs[OPT_PROTOCOL], PROTO_2);
		}
		// Send choice to server.
		snprintf(msg, sizeof(msg), "protocol=%d",
			get_e_protocol(confs[OPT_PROTOCOL]));
		if(asfd->write_str(asfd, CMD_GEN, msg))
			goto end;
		logp("Using protocol=%d\n",
			get_e_protocol(confs[OPT_PROTOCOL]));
	}
	else if(server_supports(feat, ":forceproto=1:"))
	{
		logp("Server is forcing protocol 1\n");
		if(get_e_protocol(confs[OPT_PROTOCOL])!=PROTO_AUTO
		  && get_e_protocol(confs[OPT_PROTOCOL])!=PROTO_1)
		{
			logp("But client has set protocol=%d!\n",
				get_e_protocol(confs[OPT_PROTOCOL]));
			goto end;
		}
		set_e_protocol(confs[OPT_PROTOCOL], PROTO_1);
	}
	else if(server_supports(feat, ":forceproto=2:"))
	{
		logp("Server is forcing protocol 2\n");
		if(get_e_protocol(confs[OPT_PROTOCOL])!=PROTO_AUTO
		  && get_e_protocol(confs[OPT_PROTOCOL])!=PROTO_2)
		{
			logp("But client has set protocol=%d!\n",
				get_e_protocol(confs[OPT_PROTOCOL]));
			goto end;
		}
		set_e_protocol(confs[OPT_PROTOCOL], PROTO_2);
	}

	if(server_supports(feat, ":msg:"))
	{
		set_int(confs[OPT_MESSAGE], 1);
		if(asfd->write_str(asfd, CMD_GEN, "msg"))
			goto end;
	}

#ifndef RS_DEFAULT_STRONG_LEN
	if(server_supports(feat, ":rshash=blake2:"))
	{
		set_e_rshash(confs[OPT_RSHASH], RSHASH_BLAKE2);
		// Send choice to server.
		if(asfd->write_str(asfd, CMD_GEN, "rshash=blake2"))
			goto end;
	}
	else
#endif
		set_e_rshash(confs[OPT_RSHASH], RSHASH_MD4);

	if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end")
	  || asfd->read_expect(asfd, CMD_GEN, "extra_comms_end ok"))
	{
		logp("Problem requesting extra_comms_end\n");
		goto end;
	}

	ret=0;
end:
	return ret;
}
Example #21
0
static int run_restore(struct asfd *asfd,
	struct sdirs *sdirs, struct conf **cconfs, int srestore)
{
	int ret=-1;
	char *cp=NULL;
	char *copy=NULL;
	enum action act;
	char *backupnostr=NULL;
	char *restoreregex=NULL;
	char *dir_for_notify=NULL;
	struct iobuf *rbuf=asfd->rbuf;
	const char *cname=get_string(cconfs[OPT_CNAME]);

	if(!(copy=strdup_w(rbuf->buf, __func__)))
		goto end;

	iobuf_free_content(rbuf);

	if(!strncmp_w(copy, "restore ")) act=ACTION_RESTORE;
	else act=ACTION_VERIFY;

	if(!(backupnostr=strchr(copy, ' ')))
	{
		logp("Could not parse %s in %s\n", copy, __func__);
		goto end;
	}
	backupnostr++;
	if(set_string(cconfs[OPT_BACKUP], backupnostr))
		goto end;
	// FIX THIS.
	if((cp=strchr(cconfs[OPT_BACKUP]->data.s, ':'))) *cp='\0';

	if(act==ACTION_RESTORE)
	{
		int r;
		if((r=client_can_restore(cconfs))<0)
			goto end;
		else if(!r)
		{
			logp("Not allowing restore of %s\n", cname);
			if(!asfd->write_str(asfd, CMD_GEN,
				"Client restore is not allowed")) ret=0;
			goto end;
		}
	}
	if(act==ACTION_VERIFY
	  && !(client_can_generic(cconfs, OPT_CLIENT_CAN_VERIFY)))
	{
		logp("Not allowing verify of %s\n", cname);
		if(!asfd->write_str(asfd, CMD_GEN,
			"Client verify is not allowed")) ret=0;
		goto end;
	}

	if((restoreregex=strchr(copy, ':')))
	{
		*restoreregex='\0';
		restoreregex++;
	}
	if(restoreregex && *restoreregex
	  && set_string(cconfs[OPT_REGEX], restoreregex))
		goto end;
	if(asfd->write_str(asfd, CMD_GEN, "ok"))
		goto end;
	ret=do_restore_server(asfd, sdirs, act,
		srestore, &dir_for_notify, cconfs);
	if(dir_for_notify)
		maybe_do_notification(asfd, ret,
			sdirs->client, dir_for_notify,
			act==ACTION_RESTORE?"restorelog":"verifylog",
			act==ACTION_RESTORE?"restore":"verify",
			cconfs);
end:
	free_w(&copy);
	free_w(&dir_for_notify);
	return ret;
}