diff --git a/irc/getters.go b/irc/getters.go index 00f31fd6..fafd76f7 100644 --- a/irc/getters.go +++ b/irc/getters.go @@ -11,6 +11,7 @@ import ( "github.com/oragono/oragono/irc/languages" "github.com/oragono/oragono/irc/modes" + "github.com/oragono/oragono/irc/utils" ) func (server *Server) Config() (config *Config) { @@ -71,6 +72,7 @@ type SessionData struct { hostname string certfp string deviceID string + connInfo string sessionID int64 } @@ -91,6 +93,7 @@ func (client *Client) AllSessionData(currentSession *Session) (data []SessionDat certfp: session.certfp, deviceID: session.deviceID, sessionID: session.sessionID, + connInfo: utils.DescribeConn(session.socket.conn.UnderlyingConn().Conn), } if session.proxiedIP != nil { data[i].ip = session.proxiedIP diff --git a/irc/nickserv.go b/irc/nickserv.go index 6e97c702..e0f78065 100644 --- a/irc/nickserv.go +++ b/irc/nickserv.go @@ -12,7 +12,6 @@ import ( "github.com/goshuirc/irc-go/ircfmt" - "github.com/oragono/oragono/irc/modes" "github.com/oragono/oragono/irc/passwd" "github.com/oragono/oragono/irc/sno" "github.com/oragono/oragono/irc/utils" @@ -1099,20 +1098,19 @@ func nsClientsHandler(server *Server, client *Client, command string, params []s nsClientsLogoutHandler(server, client, params, rb) default: nsNotice(rb, client.t("Invalid parameters")) - return } } func nsClientsListHandler(server *Server, client *Client, params []string, rb *ResponseBuffer) { target := client + hasPrivs := client.HasRoleCapabs("local_ban") if 0 < len(params) { target = server.clients.Get(params[0]) if target == nil { nsNotice(rb, client.t("No such nick")) return } - // same permissions check as RPL_WHOISACTUALLY for now: - if target != client && !client.HasMode(modes.Operator) { + if target != client && !hasPrivs { nsNotice(rb, client.t("Command restricted")) return } @@ -1131,6 +1129,9 @@ func nsClientsListHandler(server *Server, client *Client, params []string, rb *R } nsNotice(rb, fmt.Sprintf(client.t("IP address: %s"), session.ip.String())) nsNotice(rb, fmt.Sprintf(client.t("Hostname: %s"), session.hostname)) + if hasPrivs { + nsNotice(rb, fmt.Sprintf(client.t("Connection: %s"), session.connInfo)) + } nsNotice(rb, fmt.Sprintf(client.t("Created at: %s"), session.ctime.Format(time.RFC1123))) nsNotice(rb, fmt.Sprintf(client.t("Last active: %s"), session.atime.Format(time.RFC1123))) if session.certfp != "" { diff --git a/irc/server.go b/irc/server.go index f6cfd87e..11e8ddd7 100644 --- a/irc/server.go +++ b/irc/server.go @@ -443,7 +443,7 @@ func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) { if tOper != nil { rb.Add(nil, client.server.name, RPL_WHOISOPERATOR, cnick, tnick, tOper.WhoisLine) } - if client.HasMode(modes.Operator) || client == target { + if client == target || client.HasRoleCapabs("local_ban") { rb.Add(nil, client.server.name, RPL_WHOISACTUALLY, cnick, tnick, fmt.Sprintf("%s@%s", targetInfo.username, target.RawHostname()), target.IPString(), client.t("Actual user@host, Actual IP")) } if target.HasMode(modes.TLS) { diff --git a/irc/utils/net.go b/irc/utils/net.go index 451c56a0..3c3a55f1 100644 --- a/irc/utils/net.go +++ b/irc/utils/net.go @@ -5,6 +5,7 @@ package utils import ( + "fmt" "net" "regexp" "strings" @@ -193,3 +194,11 @@ func HandleXForwardedFor(remoteAddr string, xForwardedFor string, whitelist []ne // or nil: return } + +func DescribeConn(conn net.Conn) string { + // XXX for unix domain sockets, this is not informative enough for an operator + // to determine who holds the other side of the connection. there seems to be + // no way to get either the correct file descriptor of the connection, or the + // udiag_ino from `man 7 sock_diag`. maybe there's something else we can do? + return fmt.Sprintf("%s <-> %s", conn.LocalAddr().String(), conn.RemoteAddr().String()) +}