From patchwork Tue Jul 28 11:46:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kinglong Mee X-Patchwork-Id: 6884041 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C203BC05AC for ; Tue, 28 Jul 2015 11:46:49 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 73B002065D for ; Tue, 28 Jul 2015 11:46:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1B3AE20654 for ; Tue, 28 Jul 2015 11:46:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752190AbbG1Lqq (ORCPT ); Tue, 28 Jul 2015 07:46:46 -0400 Received: from mail-pa0-f47.google.com ([209.85.220.47]:34643 "EHLO mail-pa0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751323AbbG1Lqp (ORCPT ); Tue, 28 Jul 2015 07:46:45 -0400 Received: by pacan13 with SMTP id an13so70173485pac.1 for ; Tue, 28 Jul 2015 04:46:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:cc:subject :content-type:content-transfer-encoding; bh=Myya3SG4Y6G08xvLOE40AxGORW5SW4Be25kkTgCcc2U=; b=LwakZg2iMpRDxBNrimjHT6FSaqKdACwVV682uAEdCp+5QWxTNE2QcecJhsxzq5S1Lu V3njPHRgm6iG78zuEWlR0yYzjhSb9JA+tjdjNIqadvg2eLAbN8gczZKG9aqUaLumM/VI k2iZ9bD/78rWbMM9qfUjN+Sz4G1OQ7cma6fJFwG1DflynAFnKwerCTH1XcoXOvrsasHG royGYEQ5iGKruPS2UNWSE/D+BSHckMYeVeDHVC21sX3jvuqXOsvggwfiE3IXax5Vmfzn /kW1hNL+mBJiGRgvOzkJs9dOgqrTibV4dZ+kwJVZR4tBwjlPSY7F8RTyT3JS9FYTuak5 GbQg== X-Received: by 10.67.3.9 with SMTP id bs9mr79855699pad.136.1438084005152; Tue, 28 Jul 2015 04:46:45 -0700 (PDT) Received: from [192.168.99.4] ([104.143.41.79]) by smtp.googlemail.com with ESMTPSA id ij17sm34988867pac.4.2015.07.28.04.46.40 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jul 2015 04:46:44 -0700 (PDT) Message-ID: <55B76B94.4060208@gmail.com> Date: Tue, 28 Jul 2015 19:46:28 +0800 From: Kinglong Mee User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: "J. Bruce Fields" , "linux-nfs@vger.kernel.org" CC: tigran.mkrtchyan@desy.de, kinglongmee@gmail.com Subject: [PATCH 1/4] 4.0 setclientid: More cases for setclientid behavior Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-8.2 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP More cases of RFC 7530 16.33.5 setclientid/setclientid_confirm behavior. Signed-off-by: Kinglong Mee --- nfs4.0/servertests/st_setclientid.py | 245 ++++++++++++++++++++++++++++++++--- 1 file changed, 227 insertions(+), 18 deletions(-) diff --git a/nfs4.0/servertests/st_setclientid.py b/nfs4.0/servertests/st_setclientid.py index e9d0052..ca3e1d4 100644 --- a/nfs4.0/servertests/st_setclientid.py +++ b/nfs4.0/servertests/st_setclientid.py @@ -49,25 +49,7 @@ def testClientUpdateCallback(t, env): c.init_connection(id, verf) res = c.close_file(t.code, fh, stateid) check(res, msg="Close after updating callback info") - -def testInUse(t, env): - """SETCLIENTID with same nfs_client_id.id should return NFS4ERR_CLID_INUSE - This requires NCL1 and NCL2 to have different principals (UIDs). - - FLAGS: setclientid setclientidconfirm all - DEPEND: _checkprinciples INIT - CODE: CID2 - """ - c1 = env.c1 - c2 = env.c2 - c1.init_connection("Badid_for_%s_pid=%i" % (t.code, os.getpid()), - verifier=c1.verifier) - ops = [c2.setclientid(id="Badid_for_%s_pid=%i" % (t.code, os.getpid()), - verifier=c1.verifier)] - res = c2.compound(ops) - check(res, NFS4ERR_CLID_INUSE, "SETCLIENTID with same nfs_client_id.id") - def testLoseAnswer(t, env): """SETCLIENTID after a client reboot could cause case not covered in RFC @@ -114,7 +96,234 @@ def testAllCases(t, env): # (*xc*s), (*xd*t) res = c.compound([c.setclientid(id=id, verifier='')]) check(res) + +def testInUse(t, env): + """SETCLIENTID with same nfs_client_id.id should return NFS4ERR_CLID_INUSE + + This requires NCL1 and NCL2 to have different principals (UIDs). + FLAGS: setclientid setclientidconfirm all + DEPEND: _checkprinciples INIT + CODE: CID4a + """ + c1 = env.c1 + c2 = env.c2 + clid = "Clid_for_%s_pid=%i" % (t.code, os.getpid()) + c1.init_connection(clid, verifier=c1.verifier) + ops = [c2.setclientid(clid, verifier=c1.verifier)] + res = c2.compound(ops) + check(res, NFS4ERR_CLID_INUSE, "SETCLIENTID with same nfs_client_id.id") + +def testCallbackInfoUpdate(t, env): + """A probable callback information update and records + an unconfirmed { v, x, c, k, t } and leaves the + confirmed { v, x, c, l, s } in place, such that t != s. + + FLAGS: setclientid all + DEPEND: INIT + CODE: CID4b + """ + c1 = env.c1 + clid = "Clid_for_%s_pid=%i" % (t.code, os.getpid()) + + # confirmed { v, x, c, l, s } + (cclientid, cconfirm) = c1.init_connection(clid, verifier=c1.verifier) + + # request { v, x, c, k, s } --> unconfirmed { v, x, c, k, t } + ops = [c1.setclientid(clid, verifier=c1.verifier)] + res = c1.compound(ops) + check(res) + + tclientid = res.resarray[0].switch.switch.clientid + tconfirm = res.resarray[0].switch.switch.setclientid_confirm + + # (t != s) + if tconfirm == '\x00\x00\x00\x00\x00\x00\x00\x00': + t.fail("Got clientid confirm verifier with all zero!") + + if cclientid != tclientid: + t.fail("Return a different clientID for callback information updating!") + + if tconfirm == cconfirm: + t.fail("Return a same confirm for callback information updating!") + +def testConfirmedDiffVerifier(t, env): + """The server has previously recorded a confirmed { u, x, c, l, s } + record such that v != u, l may or may not equal k, and has not + recorded any unconfirmed { *, x, *, *, * } record for x. The + server records an unconfirmed { v, x, d, k, t } (d != c, t != s). + + FLAGS: setclientid all + DEPEND: INIT + CODE: CID4c + """ + c1 = env.c1 + clid = "Clid_for_%s_pid=%i" % (t.code, os.getpid()) + + # confirmed { u, x, c, l, s } + (cclientid, cconfirm) = c1.init_connection(clid, verifier=c1.verifier) + + # request { v, x, c, k, s } --> unconfirmed { v, x, d, k, t } + ops = [c1.setclientid(clid, verifier="diff")] + res = c1.compound(ops) + check(res) + + tclientid = res.resarray[0].switch.switch.clientid + tconfirm = res.resarray[0].switch.switch.setclientid_confirm + + # (d != c, t != s) + if tconfirm == '\x00\x00\x00\x00\x00\x00\x00\x00': + t.fail("Got clientid confirm verifier with all zero!") + + if cclientid == tclientid: + t.fail("Return a same clientID for different verifier!") + + if tconfirm == cconfirm: + t.fail("Return a same confirm for different verifier!") + +def testConfUnConfDiffVerifier1(t, env): + """The server has previously recorded a confirmed { u, x, c, l, s } + record such that v != u, l may or may not equal k, and recorded an + unconfirmed { w, x, d, m, t } record such that c != d, t != s, m + may or may not equal k, m may or may not equal l, and k may or may + not equal l. Whether w == v or w != v makes no difference. The + server simply removes the unconfirmed { w, x, d, m, t } record and + replaces it with an unconfirmed { v, x, e, k, r } record, such + that e != d, e != c, r != t, r != s. + + FLAGS: setclientid all + DEPEND: INIT + CODE: CID4d1 + """ + c1 = env.c1 + clid = "Clid_for_%s_pid=%i" % (t.code, os.getpid()) + + # confirmed { u, x, c, l, s } + (cclientid, cconfirm) = c1.init_connection(clid, verifier=c1.verifier) + + # unconfirmed { w, x, d, m, t } + ops = [c1.setclientid(clid, verifier="unconf")] + res = c1.compound(ops) + check(res) + + uclientid = res.resarray[0].switch.switch.clientid + uconfirm = res.resarray[0].switch.switch.setclientid_confirm + + # request { v, x, c, k, s } --> unconfirmed { v, x, e, k, r } + # (v == w) + ops = [c1.setclientid(clid, verifier="unconf")] + res = c1.compound(ops) + check(res) + + tclientid = res.resarray[0].switch.switch.clientid + tconfirm = res.resarray[0].switch.switch.setclientid_confirm + + # removes the unconfirmed { w, x, d, m, t } + ops = [c1.setclientid_confirm_op(uclientid, uconfirm)] + res = c1.compound(ops) + check(res, NFS4ERR_STALE_CLIENTID) + + # (e != d, e != c, r != t, r != s) + if tconfirm == '\x00\x00\x00\x00\x00\x00\x00\x00': + t.fail("Got clientid confirm verifier with all zero!") + + if cclientid == tclientid or uclientid == tclientid: + t.fail("Return a same clientID for different verifier!") + + if tconfirm == cconfirm or tconfirm == uconfirm: + t.fail("Return a same confirm for different verifier!") + +def testConfUnConfDiffVerifier2(t, env): + """Whether w == v or w != v makes no difference. + + FLAGS: setclientid all + DEPEND: INIT + CODE: CID4d2 + """ + c1 = env.c1 + clid = "Clid_for_%s_pid=%i" % (t.code, os.getpid()) + + # confirmed { u, x, c, l, s } + (cclientid, cconfirm) = c1.init_connection(clid, verifier=c1.verifier) + + # unconfirmed { w, x, d, m, t } + ops = [c1.setclientid(clid, verifier="unconf")] + res = c1.compound(ops) + check(res) + + uclientid = res.resarray[0].switch.switch.clientid + uconfirm = res.resarray[0].switch.switch.setclientid_confirm + + # request { v, x, c, k, s } --> unconfirmed { v, x, e, k, r } + # (v != w) + ops = [c1.setclientid(clid, verifier="testconf")] + res = c1.compound(ops) + check(res) + + tclientid = res.resarray[0].switch.switch.clientid + tconfirm = res.resarray[0].switch.switch.setclientid_confirm + + # removes the unconfirmed { w, x, d, m, t } + ops = [c1.setclientid_confirm_op(uclientid, uconfirm)] + res = c1.compound(ops) + check(res, NFS4ERR_STALE_CLIENTID) + + # (e != d, e != c, r != t, r != s) + if tconfirm == '\x00\x00\x00\x00\x00\x00\x00\x00': + t.fail("Got clientid confirm verifier with all zero!") + + if cclientid == tclientid or uclientid == tclientid: + t.fail("Return a same clientID for different verifier!") + + if tconfirm == cconfirm or tconfirm == uconfirm: + t.fail("Return a same confirm for different verifier!") + +def testUnConfReplaced(t, env): + """The server has no confirmed { *, x, *, *, * } for x. It may or + may not have recorded an unconfirmed { u, x, c, l, s }, where l + may or may not equal k, and u may or may not equal v. Any + unconfirmed record { u, x, c, l, * }, regardless of whether u == v + or l == k, is replaced with an unconfirmed record { v, x, d, k, t} + where d != c, t != s. + + FLAGS: setclientid all + DEPEND: INIT + CODE: CID4e + """ + c1 = env.c1 + clid = "Clid_for_%s_pid=%i" % (t.code, os.getpid()) + + # unconfirmed { w, x, d, m, t } + ops = [c1.setclientid(clid, verifier="unconf")] + res = c1.compound(ops) + check(res) + + uclientid = res.resarray[0].switch.switch.clientid + uconfirm = res.resarray[0].switch.switch.setclientid_confirm + + # request { v, x, c, k, s } --> unconfirmed { v, x, d, k, t } + ops = [c1.setclientid(clid, verifier="diff")] + res = c1.compound(ops) + check(res) + + tclientid = res.resarray[0].switch.switch.clientid + tconfirm = res.resarray[0].switch.switch.setclientid_confirm + + # removes the unconfirmed { w, x, d, m, t } + ops = [c1.setclientid_confirm_op(uclientid, uconfirm)] + res = c1.compound(ops) + check(res, NFS4ERR_STALE_CLIENTID) + + # (d != c, t != s) + if tconfirm == '\x00\x00\x00\x00\x00\x00\x00\x00': + t.fail("Got clientid confirm verifier with all zero!") + + if uclientid == tclientid: + t.fail("Return a same clientID for different verifier!") + + if tconfirm == uconfirm: + t.fail("Return a same confirm for different verifier!") + def testLotsOfClients(t, env): """SETCLIENTID called multiple times