The branch, master has been updated via 51dae12c Update NEWS. via 95073031 Fix bug with validing remote filter rules. via 81c5c813 Mention the filename when unpack_smb_acl() returns an error. via a6a0d2f7 Require a newer protocol to specify the digest list. via 418e38a8 Talk about the new daemon greeting line. via b2dcabdb Improve output of "N-bit" items in json data. from ad53a9b5 Also change dashes in the dict var names to make jq use easier.
https://git.samba.org/?p=rsync.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 51dae12c929d55cf4d5eb95c088910342809bcc5 Author: Wayne Davison <wa...@opencoder.net> Date: Mon Sep 12 22:04:33 2022 -0700 Update NEWS. commit 950730313de994d191ba2d5be575e97690b355e8 Author: Wayne Davison <wa...@opencoder.net> Date: Mon Sep 12 22:02:00 2022 -0700 Fix bug with validing remote filter rules. commit 81c5c81381d86d84fca3a2681ad0c2027bc65d6e Author: Wayne Davison <wa...@opencoder.net> Date: Sun Sep 11 10:03:16 2022 -0700 Mention the filename when unpack_smb_acl() returns an error. commit a6a0d2f77c7d1f06829c301914585a3d873fcd39 Author: Wayne Davison <wa...@opencoder.net> Date: Sat Sep 10 21:52:54 2022 -0700 Require a newer protocol to specify the digest list. commit 418e38a8789fd9b668961f945382c78806f2fb20 Author: Wayne Davison <wa...@opencoder.net> Date: Sat Sep 10 21:30:46 2022 -0700 Talk about the new daemon greeting line. commit b2dcabdbb9a50074655bd731425c13cea5874c76 Author: Wayne Davison <wa...@opencoder.net> Date: Sat Sep 10 21:05:07 2022 -0700 Improve output of "N-bit" items in json data. ----------------------------------------------------------------------- Summary of changes: NEWS.md | 4 +++- acls.c | 1 + clientserver.c | 12 ++++++++--- csprotocol.txt | 52 ++++++++++++++++++++++++++++++++-------------- exclude.c | 35 ++++++++++++++++++------------- flist.c | 2 +- rsync.h | 1 + support/json-rsync-version | 13 ++++++++---- usage.c | 11 +++++++--- 9 files changed, 89 insertions(+), 42 deletions(-) Changeset truncated at 500 lines: diff --git a/NEWS.md b/NEWS.md index fe962ad0..44eddd9b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,7 +4,9 @@ ### BUG FIXES: -- ... +- Fix a bug with validating remote filter rules. + +- When rsync gets and unpack error on an ACL, mention the filename. ### ENHANCEMENTS: diff --git a/acls.c b/acls.c index 12e662cf..3cf12eeb 100644 --- a/acls.c +++ b/acls.c @@ -519,6 +519,7 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl, sys_acl_free_acl(sacl); if (!ok) { + rsyserr(FERROR_XFER, errno, "get_acl: unpack_smb_acl(%s)", fname); return -1; } } else if (no_acl_syscall_error(errno)) { diff --git a/clientserver.c b/clientserver.c index 7436d01e..9ad7eaf7 100644 --- a/clientserver.c +++ b/clientserver.c @@ -184,11 +184,11 @@ static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int } if (remote_sub < 0) { - if (remote_protocol == 30) { + if (remote_protocol >= 30) { if (am_client) - rprintf(FERROR, "rsync: server is speaking an incompatible beta of protocol 30\n"); + rprintf(FERROR, "rsync: the server omitted the subprotocol value: %s\n", buf); else - io_printf(f_out, "@ERROR: your client is speaking an incompatible beta of protocol 30\n"); + io_printf(f_out, "@ERROR: your client omitted the subprotocol value: %s\n", buf); return -1; } remote_sub = 0; @@ -200,6 +200,12 @@ static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int daemon_auth_choices = strdup(daemon_auth_choices + 1); if ((cp = strchr(daemon_auth_choices, '\n')) != NULL) *cp = '\0'; + } else if (remote_protocol > 31) { + if (am_client) + rprintf(FERROR, "rsync: the server omitted the digest name list: %s\n", buf); + else + io_printf(f_out, "@ERROR: your client omitted the digest name list: %s\n", buf); + return -1; } if (protocol_version > remote_protocol) { diff --git a/csprotocol.txt b/csprotocol.txt index c8dadd41..4c7ec5b8 100644 --- a/csprotocol.txt +++ b/csprotocol.txt @@ -7,39 +7,54 @@ basically a summary of clientserver.c and authenticate.c. This is the protocol used for rsync --daemon; i.e. connections to port 873 rather than invocations over a remote shell. -When the server accepts a connection, it prints a greeting +When the server accepts a connection, it prints a newline-terminated +greeting line: - @RSYNCD: <version>.<subprotocol> + @RSYNCD: <version>.<subprotocol> <digest1> <digestN> -where <version> is the numeric version (see PROTOCOL_VERSION in rsync.h) -'.' is a literal period, and <subprotocol> is the numeric subprotocol -version (see SUBPROTOCOL_VERSION -- it will be 0 for final releases). -Protocols prior to 30 only output <version> alone. The daemon expects -to see a similar greeting back from the client. For protocols prior to -30, an absent ".<subprotocol>" value is assumed to be 0. For protocol -30, an absent value is a fatal error. The daemon then follows this line -with a free-format text message-of-the-day (if any is defined). +The <version> is the numeric version (see PROTOCOL_VERSION in rsync.h) +The <subprotocol> is the numeric subprotocol version (which is 0 for a +final protocol version, as the SUBPROTOCOL_VERSION define discusses). +The <digestN> names are the authentication digest algorithms that the +daemon supports, listed in order of preference. + +An rsync prior to 3.2.7 omits the digest names. An rsync prior to 3.0.0 +also omits the period and the <subprotocol> value. Since a final +protocol has a subprotocol value of 0, a missing subprotocol value is +assumed to be 0 for any protocol prior to 30. It is considered a fatal +error for protocol 30 and above to omit it. It is considered a fatal +error for protocol 32 and above to omit the digest name list (currently +31 is the newest protocol). + +The daemon expects to see a similar greeting line back from the client. +Once received, the daemon follows the opening line with a free-format +text message-of-the-day (if any is defined). The server is now in the connected state. The client can either send -the command +the command: #list -to get a listing of modules, or the name of a module. After this, the +(to get a listing of modules) or the name of a module. After this, the connection is now bound to a particular module. Access per host for this module is now checked, as is per-module connection limits. -If authentication is required to use this module, the server will say +If authentication is required to use this module, the server will say: @RSYNCD: AUTHREQD <challenge> where <challenge> is a random string of base64 characters. The client -must respond with +must respond with: <user> <response> -where <user> is the username they claim to be, and <response> is the -base64 form of the MD4 hash of challenge+password. +The <user> is the username they claim to be. The <response> is the +base64 form of the digest hash of the challenge+password string. The +chosen digest method is the most preferred client method that is also in +the server's list. If no digest list was explicitly provided, the side +expecting a list assumes the other side provided either the single name +"md5" (for a negotiated protocol 30), or the single name "md4" (for an +older protocol). At this point the server applies all remaining constraints before handing control to the client, including switching uid/gid, setting up @@ -76,6 +91,11 @@ stay tuned (or write it yourself!). ------------ Protocol version changes +31 (2022-09-10, 3.2.7dev) + + The use of a suffixed list of digest names was added as an + optional suffix to the greeting line. + 30 (2007-10-04, 3.0.0pre1) The use of a ".<subprotocol>" number was added to diff --git a/exclude.c b/exclude.c index 5458455b..4022e824 100644 --- a/exclude.c +++ b/exclude.c @@ -78,6 +78,10 @@ static filter_rule **mergelist_parents; static int mergelist_cnt = 0; static int mergelist_size = 0; +#define LOCAL_RULE 1 +#define REMOTE_RULE 2 +static uchar cur_elide_value = REMOTE_RULE; + /* Each filter_list_struct describes a singly-linked list by keeping track * of both the head and tail pointers. The list is slightly unusual in that * a parent-dir's content can be appended to the end of the local list in a @@ -220,6 +224,7 @@ static void add_rule(filter_rule_list *listp, const char *pat, unsigned int pat_ slash_cnt++; } } + rule->elide = 0; strlcpy(rule->pattern + pre_len, pat, pat_len + 1); pat_len += pre_len; if (suf_len) { @@ -900,7 +905,7 @@ static int rule_matches(const char *fname, filter_rule *ex, int name_flags) const char *strings[16]; /* more than enough */ const char *name = fname + (*fname == '/'); - if (!*name) + if (!*name || ex->elide == cur_elide_value) return 0; if (!(name_flags & NAME_IS_XATTR) ^ !(ex->rflags & FILTRULE_XATTR)) @@ -1016,6 +1021,15 @@ int name_is_excluded(const char *fname, int name_flags, int filter_level) return 0; } +int check_server_filter(filter_rule_list *listp, enum logcode code, const char *name, int name_flags) +{ + int ret; + cur_elide_value = LOCAL_RULE; + ret = check_filter(listp, code, name, name_flags); + cur_elide_value = REMOTE_RULE; + return ret; +} + /* Return -1 if file "name" is defined to be excluded by the specified * exclude list, 1 if it is included, and 0 if it was not matched. */ int check_filter(filter_rule_list *listp, enum logcode code, @@ -1571,7 +1585,7 @@ char *get_rule_prefix(filter_rule *rule, const char *pat, int for_xfer, static void send_rules(int f_out, filter_rule_list *flp) { - filter_rule *ent, *prev = NULL; + filter_rule *ent; for (ent = flp->head; ent; ent = ent->next) { unsigned int len, plen, dlen; @@ -1586,21 +1600,15 @@ static void send_rules(int f_out, filter_rule_list *flp) * merge files as an optimization (since they can only have * include/exclude rules). */ if (ent->rflags & FILTRULE_SENDER_SIDE) - elide = am_sender ? 1 : -1; + elide = am_sender ? LOCAL_RULE : REMOTE_RULE; if (ent->rflags & FILTRULE_RECEIVER_SIDE) - elide = elide ? 0 : am_sender ? -1 : 1; + elide = elide ? 0 : am_sender ? REMOTE_RULE : LOCAL_RULE; else if (delete_excluded && !elide && (!(ent->rflags & FILTRULE_PERDIR_MERGE) || ent->rflags & FILTRULE_NO_PREFIXES)) - elide = am_sender ? 1 : -1; - if (elide < 0) { - if (prev) - prev->next = ent->next; - else - flp->head = ent->next; - } else - prev = ent; - if (elide > 0) + elide = am_sender ? LOCAL_RULE : REMOTE_RULE; + ent->elide = elide; + if (elide == LOCAL_RULE) continue; if (ent->rflags & FILTRULE_CVS_IGNORE && !(ent->rflags & FILTRULE_MERGE_FILE)) { @@ -1628,7 +1636,6 @@ static void send_rules(int f_out, filter_rule_list *flp) if (dlen) write_byte(f_out, '/'); } - flp->tail = prev; } /* This is only called by the client. */ diff --git a/flist.c b/flist.c index 0313db54..db11b353 100644 --- a/flist.c +++ b/flist.c @@ -991,7 +991,7 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x if (*thisname != '.' || thisname[1] != '\0') { int filt_flags = S_ISDIR(mode) ? NAME_IS_DIR : NAME_IS_FILE; if (!trust_sender_filter /* a per-dir filter rule means we must trust the sender's filtering */ - && filter_list.head && check_filter(&filter_list, FINFO, thisname, filt_flags) < 0) { + && filter_list.head && check_server_filter(&filter_list, FINFO, thisname, filt_flags) < 0) { rprintf(FERROR, "ERROR: rejecting excluded file-list name: %s\n", thisname); exit_cleanup(RERR_PROTOCOL); } diff --git a/rsync.h b/rsync.h index f0d3dd0b..0a5ff809 100644 --- a/rsync.h +++ b/rsync.h @@ -1024,6 +1024,7 @@ typedef struct filter_struct { int slash_cnt; struct filter_list_struct *mergelist; } u; + uchar elide; } filter_rule; typedef struct filter_list_struct { diff --git a/support/json-rsync-version b/support/json-rsync-version index afaf7382..a51c3a88 100755 --- a/support/json-rsync-version +++ b/support/json-rsync-version @@ -35,13 +35,18 @@ def main(): for x in line.strip(' ,').split(', '): if ' ' in x: val, var = x.split(' ', 1) + if val == 'no': + val = False + elif val.endswith('-bit'): + var = var[:-1] + '_bits' + val = int(val.split('-')[0]) if var == 'protect-args': var = 'secluded-args' - var = var.replace(' ', '_').replace('-', '_') - info[sect_name][var] = False if val == 'no' else val else: - x = x.replace('-', '_') - info[sect_name][x] = True + var = x + val = True + var = var.replace(' ', '_').replace('-', '_') + info[sect_name][var] = val else: info[sect_name] += [ x for x in line.split() if not x.startswith('(') ] elif line == '': diff --git a/usage.c b/usage.c index a2c2a3f0..7f215a02 100644 --- a/usage.c +++ b/usage.c @@ -172,13 +172,18 @@ static void print_info_flags(enum logcode f) else if (as_json) { char *space = strchr(str, ' '); int is_no = space && strncmp(str, "no ", 3) == 0; - char *quot = space && !is_no ? "\"" : ""; + int is_bits = space && isDigit(str); + char *quot = space && !is_no && !is_bits ? "\"" : ""; char *item = space ? space + 1 : str; char *val = !space ? "true" : is_no ? "false" : str; int val_len = !space ? 4 : is_no ? 5 : space - str; + if (is_bits && (space = strchr(val, '-')) != NULL) + val_len = space - str; item_len = snprintf(item_buf, sizeof item_buf, - " \"%s\": %s%.*s%s%s", item, quot, val_len, val, quot, - need_comma ? "," : ""); + " \"%s%s\": %s%.*s%s%s", item, is_bits ? "bits" : "", + quot, val_len, val, quot, need_comma ? "," : ""); + if (is_bits) + item_buf[strlen(item)+2-1] = '_'; /* Turn the 's' into a '_' */ for (space = item; (space = strpbrk(space, " -")) != NULL; space++) item_buf[space - item + 2] = '_'; } else -- The rsync repository. _______________________________________________ rsync-cvs mailing list rsync-cvs@lists.samba.org https://lists.samba.org/mailman/listinfo/rsync-cvs