How to use rpcd from remote system

Hi All,

I want to call LuCI Lua RPC from remote system using rpcd
Does anyone has suggestion to how get it working.

Currently I can see config file for rpcd in /etc/config/rpcd

config login
        option username 'root'
        option password '$p$root'
        list read '*'
        list write '*'

but no way to get how to set read and write to restrict user for certain RPC only
any help would be appreciated.

1 Like

While perhaps not helpful in directly answering your question, you should be aware of

which is, as I read it, around the failure of the RPC system to properly restrict by user.

No, it is not. This is like granting an untrusted user access to your system and handing him a SUID enabled text editor. Of course he can overwrite /etc/shadow and set himself a new root password.

quite helpful link but overall rpcd ACL format yet to get acqented with as its not with much documentation.

root@OpenWrt:/# ubus list
dhcp
file
log
network
network.device
network.interface
network.interface.lan
network.interface.loopback
network.interface.wan
network.interface.wan6
network.interface.wwan
network.wireless
service
session
system
uci

root@OpenWrt:/# ubus -v list file 
'file' @c9a18b03
        "read":{"path":"String","data":"String"}
        "write":{"path":"String","data":"String"}
        "list":{"path":"String","data":"String"}
        "stat":{"path":"String","data":"String"}
        "exec":{"command":"String","params":"Array","env":"Table"}

so we can use this rpc directly in ACL thats what I have understood but why this format instead:

               "read": {
                        "ubus": {
                                "file": [ "*" ],
                                "log": [ "*" ],
                                "service": [ "*" ],
                        },
                },

big question for me for now => what is this file, log , service ????

are you trying to override existing RPC format from ubus or what ??
can we just use existing ACL in ubus RPC through json file ??

Take a look at https://git.openwrt.org/?p=project/luci2/ui.git;a=blob;f=luci2/share/acl.d/luci2.json;h=30ef91c7e929c9b8c10c2a9c10f0b62fac21fe5d;hb=e452ca693af5278ff2ddc69b6f8ed0f346c98fb1 to see an example on how to define fine grained acls.

Rules in the „read“ scope should cover side-effect free operations, like „read ssh keys“ or „list assiciated stations“ and rules in the „write“ scope should cover operations that alter system state, like „write ssh keys“ or „disable radio“ or „write uci config“.

Below the read/write scope objects there may be „ubus“ and „uci“ rules.

The „ubus“ rules are specified in the form "objectpath": ["list", "of", "functions"] where objectpath refers to a ubus object as seen by ubus list and the function list refers to names of methods exposed by the object. Both object and method names may contain wildcards.

The following ACL would grant access to the network interface status methods:

"allow-status-access": {
  "read": {
    "ubus": {
      "network.interface.*": [ "status" ]
    }
  }
}

The other kind, „uci“ rules, use a different notation in the form ["list", "of", "config", "names"].

The following ACL would define read access to /etc/config/system and write access to /etc/config/wireless:

"allow-uci-access": {
  "read": {
    "uci": [ "system" ]
  },
  "write": {
    "uci": [ "wireless" ]
  }
}

The ubus rules control which ubus methods may be invoked via the ubus http gateway while the uci rules control which configuration files may be read or written by the ubus methods in the „uci“ path (such as „ubus call uci get“, „ubus call uci set“ etc.)

The ACL names (e.g. „core“, „system“, „status“ in the linked example) are tied to user accounts through the list read and list write options in /etc/config/rpcd.

The following example would declare a user test using the password of user test from /etc/shadow and tie the read scope of the „core“ and „status“ ACLs and the write scope of the „system“ ACL to it:

config login
  option username test
  option password $p$test
  list read core
  list read status
  list write system

Granting a write scope will always imply granting the corresponding read scope, so

list read foo
list write foo

is equivalent to

list write foo

The read/write options accept wildcards too. You‘ll notice the default root login in the rpcd config which uses

list read *
list write *

This means the root login will get the read/write scope of all defined ACLs granted.

Thank you so much.
I got hope this should get working.
I have done few setup and its working, except I need to get quickly json and ubus system .

Currently I face problem while returning status to remote:

I write test user specific command to allow in to ubus interface, all works except return to remote:

usr/libexec/rpcd/testuser

but

here return is bit strange:

echo '{ "cmd_result": "$return" }'      #dont work 
##response - {"jsonrpc":"2.0","id":1,"result":[2]}

echo '{ "cmd_result": "0" }'     #this work all time 
##response - {"jsonrpc":"2.0","id":1,"result":[0,{"cmd_result":"0"}]}

whatever echo is return to ubus json rpc but echo with variable dont get output but second get return to remote without any issue.

If anything I am missing in this.
Thanks

Please refer foo example =
https://openwrt.org/docs/techref/rpcd

Can you provide a more complete example of the not working script? The above should work, but with unexpected results.

An echo '{ "cmd_result": "$return" }' will literally output { "cmd_result": "$return" } due to the single quote interpolation rules of Bash. You also need to be very careful with proper quoting and escaping when constructing JSON from external input.

Best is to use jshn (JSON Shell Notation) which will take care of constructing proper responses:

#!/bin/sh

# source jshn shell library
. /usr/share/libubox/jshn.sh

# initialize JSON output structure
json_init

# add a boolean field
json_add_boolean foo 0

# add an integer field
json_add_int code 123

# add a string, take care of escaping
json_add_string result "Some complex string\n with newlines\n and even command output: $(date)"

# add an array with three integers
json_add_array alist
json_add_int "" 1
json_add_int "" 2
json_add_int "" 3
json_close_array

# add an object (dictionary)
json_add_object adict
json_add_string foo bar
json_add_string bar baz
json_close_object

# build JSON object and print to stdout
json_dump

# will output something like this:
# { "foo": false, "code": 123, "result": "Some complex string\\n with newlines\\n and even command output: Fri Jul 13 07:11:39 CEST 2018", "alist": [ 1, 2, 3 ], "adict": { "foo": "bar", "bar": "baz" } }
1 Like

that's my mistake while writing question here - it should be

echo "{ cmd_result : $return }" #dont work

but json library safest to use what you mentioned.
I already used to test and it works well.

Thanks