fn nfs3_common_header(tx: &NFS3Transaction) -> Json
{
let js = Json::object();
- js.set_integer("xid", tx.xid as u64);
js.set_string("procedure", &nfs3_procedure_string(tx.procedure));
let file_name = String::from_utf8_lossy(&tx.file_name);
js.set_string("filename", &file_name);
let js = nfs3_common_header(tx);
js.set_string("type", "response");
- js.set_string("status", &nfs3_status_string(tx.response_status));
-
- if tx.has_creds {
- let creds_js = nfs3_creds_object(tx);
- js.set("creds", creds_js);
- }
+ js.set_string("status", &nfs3_status_string(tx.nfs_response_status));
if tx.procedure == NFSPROC3_READ {
let read_js = nfs3_file_object(tx);
return js.unwrap();
}
+
+
+#[no_mangle]
+pub extern "C" fn rs_rpc_log_json_response(tx: &mut NFS3Transaction) -> *mut JsonT
+{
+ let js = Json::object();
+ js.set_integer("xid", tx.xid as u64);
+ js.set_string("status", &rpc_status_string(tx.rpc_response_status));
+ js.set_string("auth_type", &rpc_auth_type_string(tx.auth_type));
+ if tx.auth_type == RPCAUTH_UNIX {
+ let creds_js = nfs3_creds_object(tx);
+ js.set("creds", creds_js);
+ }
+
+ return js.unwrap();
+}
/// this is the 'from' or original name.
pub file_name: Vec<u8>,
+ pub auth_type: u32,
pub request_machine_name: Vec<u8>,
pub request_uid: u32,
pub request_gid: u32,
- pub response_status: u32,
+ pub rpc_response_status: u32,
+ pub nfs_response_status: u32,
- pub has_creds: bool,
pub is_first: bool,
pub is_last: bool,
request_machine_name:Vec::new(),
request_uid:0,
request_gid:0,
- response_status:0,
- has_creds: false,
+ rpc_response_status:0,
+ nfs_response_status:0,
+ auth_type: 0,
is_first: false,
is_last: false,
request_done: false,
}
// TODO maybe not enough users to justify a func
- fn mark_response_tx_done(&mut self, xid: u32, status: u32)
+ fn mark_response_tx_done(&mut self, xid: u32, rpc_status: u32, nfs_status: u32)
{
match self.get_tx_by_xid(xid) {
Some(mut mytx) => {
mytx.response_done = true;
- mytx.response_status = status;
+ mytx.rpc_response_status = rpc_status;
+ mytx.nfs_response_status = nfs_status;
SCLogDebug!("process_reply_record: tx ID {} XID {} REQUEST {} RESPONSE {}",
mytx.id, mytx.xid, mytx.request_done, mytx.response_done);
tx.type_data = Some(NFS3TransactionTypeData::RENAME(aux_file_name));
}
+ tx.auth_type = r.creds_flavor;
match &r.creds_unix {
&Some(ref u) => {
tx.request_machine_name = u.machine_name_buf.to_vec();
tx.request_uid = u.uid;
tx.request_gid = u.gid;
- tx.has_creds = true;
},
_ => { },
}
tx.type_data = Some(NFS3TransactionTypeData::RENAME(aux_file_name));
}
+ tx.auth_type = r.creds_flavor;
match &r.creds_unix {
&Some(ref u) => {
tx.request_machine_name = u.machine_name_buf.to_vec();
tx.request_uid = u.uid;
tx.request_gid = u.gid;
- tx.has_creds = true;
},
_ => { },
}
}
fn process_reply_record_v3<'b>(&mut self, r: &RpcReplyPacket<'b>, xidmap: &mut NFS3RequestXidMap) -> u32 {
- let status;
+ let nfs_status;
if xidmap.procedure == NFSPROC3_LOOKUP {
match parse_nfs3_response_lookup(r.prog_data) {
SCLogDebug!("LOOKUP: {:?}", lookup);
SCLogDebug!("RESPONSE LOOKUP file_name {:?}", xidmap.file_name);
- status = lookup.status;
+ nfs_status = lookup.status;
SCLogDebug!("LOOKUP handle {:?}", lookup.handle);
self.namemap.insert(lookup.handle.value.to_vec(), xidmap.file_name.to_vec());
SCLogDebug!("nfs3_create_record: {:?}", nfs3_create_record);
SCLogDebug!("RESPONSE CREATE file_name {:?}", xidmap.file_name);
- status = nfs3_create_record.status;
+ nfs_status = nfs3_create_record.status;
match nfs3_create_record.handle {
Some(h) => {
match parse_nfs3_reply_read(r.prog_data) {
IResult::Done(_, ref reply) => {
self.process_read_record(r, reply, Some(&xidmap));
- status = reply.status;
+ nfs_status = reply.status;
},
IResult::Incomplete(_) => { panic!("Incomplete!"); },
IResult::Error(e) => { panic!("Parsing failed: {:?}",e); },
IResult::Done(_, ref reply) => {
//SCLogDebug!("READDIRPLUS reply {:?}", reply);
- status = reply.status;
+ nfs_status = reply.status;
// cut off final eof field
let d = &reply.data[..reply.data.len()-4 as usize];
}
_ => 0 as u32
};
- status = stat;
+ nfs_status = stat;
}
SCLogDebug!("REPLY {} to procedure {} blob size {}",
r.hdr.xid, xidmap.procedure, r.prog_data.len());
if xidmap.procedure != NFSPROC3_READ {
- self.mark_response_tx_done(r.hdr.xid, status);
+ self.mark_response_tx_done(r.hdr.xid, r.reply_state, nfs_status);
}
0
}
fn process_reply_record_v2<'b>(&mut self, r: &RpcReplyPacket<'b>, xidmap: &NFS3RequestXidMap) -> u32 {
- let status;
+ let nfs_status;
if xidmap.procedure == NFSPROC3_READ {
match parse_nfs2_reply_read(r.prog_data) {
IResult::Done(_, ref reply) => {
SCLogDebug!("NFSv2 READ reply record");
self.process_read_record(r, reply, Some(&xidmap));
- status = reply.status;
+ nfs_status = reply.status;
},
IResult::Incomplete(_) => { panic!("Incomplete!"); },
IResult::Error(e) => { panic!("Parsing failed: {:?}",e); },
}
_ => 0 as u32
};
- status = stat;
+ nfs_status = stat;
}
SCLogDebug!("REPLY {} to procedure {} blob size {}",
r.hdr.xid, xidmap.procedure, r.prog_data.len());
- self.mark_response_tx_done(r.hdr.xid, status);
+ self.mark_response_tx_done(r.hdr.xid, r.reply_state, nfs_status);
0
}
reply.count, fill_bytes as u8, reply.eof, &r.hdr.xid);
if is_last {
tdf.file_last_xid = r.hdr.xid;
- tx.response_status = reply.status;
+ tx.rpc_response_status = r.reply_state;
+ tx.nfs_response_status = reply.status;
tx.is_last = true;
tx.response_done = true;
}
tx.is_first = true;
if is_last {
tdf.file_last_xid = r.hdr.xid;
- tx.response_status = reply.status;
+ tx.rpc_response_status = r.reply_state;
+ tx.nfs_response_status = reply.status;
tx.is_last = true;
tx.response_done = true;
}
//! Nom parsers for RPC & NFSv3
-use nom::{be_u32, be_u64, rest};
+use nom::{be_u32, rest};
#[derive(Debug,PartialEq)]
pub struct RpcRequestCredsUnix<'a> {
},
}.to_string()
}
+
+pub const RPCMSG_ACCEPTED: u32 = 0;
+pub const RPCMSG_DENIED: u32 = 1;
+
+pub fn rpc_status_string(status: u32) -> String {
+ match status {
+ RPCMSG_ACCEPTED => "ACCEPTED",
+ RPCMSG_DENIED => "DENIED",
+ _ => {
+ return (status).to_string();
+ },
+ }.to_string()
+}
+
+/* http://www.iana.org/assignments/rpc-authentication-numbers/rpc-authentication-numbers.xhtml */
+/* RFC 1057 Section 7.2 */
+/* RFC 2203 Section 3 */
+
+pub const RPCAUTH_NULL: u32 = 0;
+pub const RPCAUTH_UNIX: u32 = 1;
+pub const RPCAUTH_SHORT: u32 = 2;
+pub const RPCAUTH_DH: u32 = 3;
+pub const RPCAUTH_KERB: u32 = 4;
+pub const RPCAUTH_RSA: u32 = 5;
+pub const RPCAUTH_GSS: u32 = 6;
+
+pub fn rpc_auth_type_string(auth_type: u32) -> String {
+ match auth_type {
+ RPCAUTH_NULL => "NULL",
+ RPCAUTH_UNIX => "UNIX",
+ RPCAUTH_SHORT => "SHORT",
+ RPCAUTH_DH => "DH",
+ RPCAUTH_KERB => "KERB",
+ RPCAUTH_RSA => "RSA",
+ RPCAUTH_GSS => "GSS",
+ _ => {
+ return (auth_type).to_string();
+ },
+ }.to_string()
+}
+
+/* http://www.iana.org/assignments/rpc-authentication-numbers/rpc-authentication-numbers.xhtml */
+pub const RPCAUTH_OK: u32 = 0; // success/failed at remote end [RFC5531]
+pub const RPCAUTH_BADCRED: u32 = 1; // bad credential (seal broken) [RFC5531]
+pub const RPCAUTH_REJECTEDCRED: u32 = 2; // client must begin new session [RFC5531]
+pub const RPCAUTH_BADVERF: u32 = 3; // bad verifier (seal broken) [RFC5531]
+pub const RPCAUTH_REJECTEDVERF: u32 = 4; // verifier expired or replayed [RFC5531]
+pub const RPCAUTH_TOOWEAK: u32 = 5; // rejected for security reasons/failed locally [RFC5531]
+pub const RPCAUTH_INVALIDRESP: u32 = 6; // bogus response verifier [RFC5531]
+pub const RPCAUTH_FAILED: u32 = 7; // reason unknown/AUTH_KERB errors; deprecated. See [RFC2695] [RFC5531]
+pub const RPCAUTH_KERB_GENERIC: u32 = 8; // kerberos generic error [RFC5531]
+pub const RPCAUTH_TIMEEXPIRE: u32 = 9; // time of credential expired [RFC5531]
+pub const RPCAUTH_TKT_FILE: u32 = 10; // problem with ticket file [RFC5531]
+pub const RPCAUTH_DECODE: u32 = 11; // can't decode authenticator [RFC5531]
+pub const RPCAUTH_NET_ADDR: u32 = 12; // wrong net address in ticket/RPCSEC_GSS GSS related errors [RFC5531]
+pub const RPCSEC_GSS_CREDPROBLEM: u32 = 13; // no credentials for user [RFC5531]
+pub const RPCSEC_GSS_CTXPROBLEM: u32 = 14; // problem with context [RFC5531]
+pub const RPCSEC_GSS_INNER_CREDPROBLEM: u32 = 15; // No credentials for multi-principal assertion inner context user [RFC7861]
+pub const RPCSEC_GSS_LABEL_PROBLEM: u32 = 16; // Problem with label assertion [RFC7861]
+pub const RPCSEC_GSS_PRIVILEGE_PROBLEM: u32 = 17; // Problem with structured privilege assertion [RFC7861]
+pub const RPCSEC_GSS_UNKNOWN_MESSAGE: u32 = 18; // Unknown structured privilege assertion [RFC7861]
+
+pub fn rpc_auth_status_string(auth_status: u32) -> String {
+ match auth_status {
+ RPCAUTH_OK => "OK",
+ RPCAUTH_BADCRED => "BADCRED",
+ RPCAUTH_REJECTEDCRED => "REJECTEDCRED",
+ RPCAUTH_BADVERF => "BADVERF",
+ RPCAUTH_REJECTEDVERF => "REJECTEDVERF",
+ RPCAUTH_TOOWEAK => "TOOWEAK",
+ RPCAUTH_INVALIDRESP => "NVALIDRESP",
+ RPCAUTH_FAILED => "FAILED",
+ RPCAUTH_KERB_GENERIC => "KERB_GENERIC",
+ RPCAUTH_TIMEEXPIRE => "TIMEEXPIRE",
+ RPCAUTH_TKT_FILE => "TKT_FILE",
+ RPCAUTH_DECODE => "DECODE",
+ RPCAUTH_NET_ADDR => "NET_ADDR",
+ RPCSEC_GSS_CREDPROBLEM => "GSS_CREDPROBLEM",
+ RPCSEC_GSS_CTXPROBLEM => "GSS_CTXPROBLEM",
+ RPCSEC_GSS_INNER_CREDPROBLEM => "GSS_INNER_CREDPROBLEM",
+ RPCSEC_GSS_LABEL_PROBLEM => "GSS_LABEL_PROBLEM",
+ RPCSEC_GSS_PRIVILEGE_PROBLEM => "GSS_PRIVILEGE_PROBLEM",
+ RPCSEC_GSS_UNKNOWN_MESSAGE => "GSS_UNKNOWN_MESSAGE",
+ _ => {
+ return (auth_status).to_string();
+ },
+ }.to_string()
+}
return TM_ECODE_FAILED;
}
+ json_t *rpcjs = rs_rpc_log_json_response(tx);
+ if (unlikely(rpcjs == NULL)) {
+ goto error;
+ }
+ json_object_set_new(js, "rpc", rpcjs);
+
nfs3js = rs_nfs3_log_json_response(tx);
if (unlikely(nfs3js == NULL)) {
goto error;
}
-
json_object_set_new(js, "nfs3", nfs3js);
MemBufferReset(thread->buffer);