---
title: PSS Lic Perfect Streamer Toolkit v2.0 — the node license
url: https://doc2.pstreamer.tv/en/manual/toolkit/pss_lic.html
lang: en
product: Perfect Streamer
version: 2.0.1.264
---

# PSS Lic Perfect Streamer Toolkit v2.0 — the node license

Part of the **Perfect Streamer Toolkit** — [https://pstreamer.tv](https://pstreamer.tv)

A command-line utility for managing the license of a node: it applies the license update sent by the supplier, exports the state of the key for an activation request, and moves the license from one node to another.

It works with the same protection system key as the streamer itself — a software (SL) or a hardware (HL) one. The key is reached through the **aksusbd** service of the protection system, so the utility only works where that service is running.

The tool is part of the **pstreamer** package and after installation is found at `/opt/pss/tools/pss_lic` — nothing has to be installed separately.

## When the utility is needed

The [License](../webui/administration.md#webui-license) screen can export the C2V and apply the V2C key that has been sent, but no more than that. Every operation on the key is available from the console, and only from here is the rest done:

- activating and updating the license on a node without access to the web interface;
- automation: rolling out a fleet of nodes, scheduled license renewals, checks from a monitoring system;
- transferring a license between nodes — permanently or temporarily.

The utility does not need root: the write to the secure storage is done by the protection system service, not by the utility itself. Root is only needed to write the output file into a system directory and to restart the **pss** service after the license has changed.

The initial activation of the trial license is performed not by this utility but by the `/opt/pss/tools/activate.sh` script — see [Temporary activation and startup](../first_start/index.md#first-start-activation). The script calls **pss_lic** itself and then restarts the **pss** service and enables its autostart. How a permanent license is obtained is described in [Permanent activation](../first_start/index.md#first-start-permanent-activation).

## Usage

```
pss_lic <command> [options]
```

Started with no arguments, with `-h` or with `--help`, it prints the built-in help and exits with code `0`. Options come after the command; before the command only `-h`, `--help`, `-V` and `--version` are allowed. Positional arguments are not accepted — everything is given by options.

### Commands

| Command | Purpose | Required options |
| --- | --- | --- |
| `apply` | Apply a license update to the node — a V2C, H2R or R2H file | `--in` |
| `c2v` | Export the state of the key (C2V) to send to the supplier | — |
| `fingerprint` | Export the node fingerprint | — |
| `recipient` | Export the recipient block of the node — a description of the node as the recipient of a transfer | — |
| `keys` | List the keys of the protection system visible from this node | — |
| `detach` | Transfer a product license to another node temporarily; the result is an H2R file | `--product-id` |
| `rehost` | Move the key to another node; the result is a V2C file, and the license is removed from the current node | `--key-id` |
| `cancel` | Return a temporarily transferred license early; the result is an R2H file | `--key-id` |
| `version` | Show the version of the utility and the API version of the protection system | — |
| `help` | Show the built-in help | — |

### Options

| Option | Description | Accepted by |
| --- | --- | --- |
| `-i, --in <file>` | Input data | `apply` |
| `-o, --out <file>` | Output data; `-` by default, that is stdout | all except `version` and `help` |
| `-r, --recipient <file>` | The recipient block of the receiving node | `detach`, `rehost` |
| `-k, --key-id <id>` | Key id, decimal | `c2v`, `keys`, `detach`, `rehost`, `cancel` |
| `-p, --product-id <id>` | Product id, decimal | `detach` |
| `--duration <sec>` | The period of the temporary transfer in seconds; `120` by default, `31536000` at most | `detach` |
| `--fast` | A reduced state snapshot; on a hardware (HL) key, a smaller file | `c2v` |
| `--ids` | Print only the key ids, one per line | `keys` |
| `-y, --yes` | Do not ask for confirmation | `rehost`, `cancel` |
| `-q, --quiet` | Errors only | all |
| `-v, --verbose` | A detailed log of the calls to the protection system | all |
| `-V, --version` | Show the versions and exit | all |
| `-h, --help` | Show help | all |

An option that is not listed on its command line is a syntax error, not a silently ignored flag: the utility reports, for instance, `--key-id is not valid for 'fingerprint'`, and often adds a line with the reason. The values of `--key-id`, `--product-id` and `--duration` are decimal numbers only, starting from `1`; zero is not allowed.

### Input and output

Any file argument — `--in`, `--out`, `--recipient` — accepts `-`: read from stdin, write to stdout. By default the output goes to stdout.

Only the data itself — the license blob — goes to **stdout**. Success messages, warnings and errors go to **stderr** and begin with the `pss_lic:` prefix. Thanks to this, any command can be redirected into a file or a pipe without having to parse the output.

If no output file is given and stdout is a terminal, the `detach`, `rehost` and `cancel` commands warn that the result of the transfer will end up on the screen and be lost:

```
pss_lic: writing the V2C to the terminal; use --out <file> to keep it
```

The input file is checked before the protection system is contacted: an empty file, a file containing a zero byte and a file larger than 8 MiB are rejected. A UTF-8 byte order mark at the start of the file — some mail clients and editors add one — is removed automatically.

## Applying a license update

The file sent by the supplier is applied with a single command:

```bash
# apply a licence update sent by the vendor
/opt/pss/tools/pss_lic apply --in license.v2c

# the same file through a pipe
cat license.v2c | /opt/pss/tools/pss_lic apply --in -
```

On success stderr shows:

```
pss_lic: update applied
```

**The utility does not restart the service.** A running streamer keeps the previous license in memory, so after changing the license restart the service by hand:

```bash
sudo systemctl restart pss
```

Applying the same file again is not an error: the utility reports `this V2C is already installed, nothing to do` and exits with code `0`. The repeatability of the `activate.sh` script rests on this property.

Do not confuse this message with the refusal `the update is older than the one already installed (stale or rolled-back V2C)` (status 54) — that one means an outdated file is being applied, and it exits with code `1`. In that case ask the supplier for a fresh V2C.

The `apply` command applies all three kinds of update: the V2C from the supplier, the H2R of a temporary transfer and the R2H of its return.

## Exporting the data for the supplier

An activation request, or a request to extend the license, is built from a C2V file — a snapshot of the current state of the key:

```bash
# export the key state for the vendor
/opt/pss/tools/pss_lic c2v --out host.c2v
```

If the node sees several keys, the protection system will not guess which one is meant and answers with the refusal `too many keys match the scope` (status 37). The `keys` command lists the key ids:

```bash
# list the key ids visible on this host, then scope the export to one of them
/opt/pss/tools/pss_lic keys --ids
/opt/pss/tools/pss_lic c2v --key-id <id> --out host.c2v
```

Without `--ids` the `keys` command prints the list of keys and their licenses in the form the protection system returns it — an XML document, not a table. Choosing a value for `--key-id` only needs the `--ids` form.

The `--fast` option requests a reduced state snapshot from the key. On a hardware (HL) key such a file comes out roughly an order of magnitude smaller than the full one; on a software (SL) key the size is the same — only the data it carries differs.

**The contents of a C2V cannot be read on the node**, so the key id is obtained with the `keys` command and not from the file itself.

**One C2V — one request.** Do not send the supplier the same C2V twice: the second V2C issued against it may apply only in part. To make another request, export the C2V afresh.

The `fingerprint` and `recipient` commands export the node fingerprint and the recipient block. The fingerprint describes the machine and is what the supplier needs when there is no license on the node yet: a new software key is bound to it. The recipient block describes the node as the recipient of a transfer and is needed not by the supplier but by the second node — see Transferring the license to another node. Both belong to the node as a whole rather than to an individual key, so the `--key-id` option is not valid for them.

## Transferring the license to another node

A license can be transferred between nodes only for a software (SL) key: a hardware key travels with the device itself and is not touched by the commands of the utility. A trial license is not transferable. Whether a transfer is possible is set by the terms of the license; if it is not provided for, the protection system answers with the refusal `rehost is not allowed for this licence`. Check this with the supplier in advance.

> **Warning**
>
> `rehost` removes the license from the current node. The resulting file can only be applied on the node whose recipient block was passed in `--recipient`. If the file is lost or the receiving node is unreachable, the license is lost with it: there is no local rollback. Always pass `--recipient` and save the result to a file, not to the screen.

The transfer takes three steps and involves both nodes. Below, A is the node the license leaves and B is the node it moves to.

1. On node **B**, export the recipient block and pass the file to node A:

   ```bash
   /opt/pss/tools/pss_lic recipient --out b.rcp
   ```
2. On node **A**, move the key. The utility will ask for confirmation:

   ```bash
   /opt/pss/tools/pss_lic rehost --key-id <id> --recipient b.rcp --out a2b.v2c
   ```

   ```
   pss_lic: about to move the licence off this host. This cannot be undone. Continue? [y/N]
   ```

   An answer that starts with `y` or `Y` counts as confirmation: `yes` confirms just as `y` does. Any other answer, an empty line included, cancels the operation. The question is asked directly on the terminal, so redirecting the output does not hide it. If there is no terminal — the command was started from a scheduler, say — the utility refuses to perform the transfer and suggests passing `--yes`.
3. On node **B**, apply the file received and restart the service:

   ```bash
   /opt/pss/tools/pss_lic apply --in a2b.v2c
   sudo systemctl restart pss
   ```

From the moment step 2 completes until step 3 has run, the license is on neither node. Plan the transfer so that this interval stays short.

The resulting file is useless anywhere but on node B: on another machine it gives a refusal with status 62. Applying an old file for the same key on node A gives status 70 or 71 — the key has already been moved.

## Temporary transfer of a license

`detach` transfers a product license to another node for a set period, and `cancel` returns it early. Like the permanent transfer, the temporary one works only with a software key and only if the terms of the license allow it; otherwise the protection system answers with a refusal carrying status 67. With a trial license such a refusal is the expected result, not a fault.

The product id of Perfect Streamer is `2`. The period is given in seconds with the `--duration` option; **the default is 120 seconds**, so in practice always state it explicitly. The upper bound of the utility itself is `31536000` seconds (a year), but the real limit is set by the license: with too long a period the protection system answers with the refusal `invalid duration specified`. The period asked for is exactly that — a request: the final value is decided by the key and may turn out to be shorter.

1. On node **B**, export the recipient block and pass the file to node A:

   ```bash
   /opt/pss/tools/pss_lic recipient --out b.rcp
   ```
2. On node **A**, transfer the license for a day:

   ```bash
   /opt/pss/tools/pss_lic detach --product-id 2 --duration 86400 --recipient b.rcp --out b.h2r
   ```

   ```
   pss_lic: product 2 detached, 86400 s requested
   ```
3. On node **B**, apply the file received and restart the service:

   ```bash
   /opt/pss/tools/pss_lic apply --in b.h2r
   sudo systemctl restart pss
   ```

When the period ends, the license returns to node A by itself. An early return goes the other way: the R2H file is created on the receiving node and applied on the original one. If the period has already expired by then, there is nothing to return — the utility reports `the R2H: nothing to write` and exits with code `1`.

1. On node **B**, find the id of the transferred key and cancel the transfer:

   ```bash
   /opt/pss/tools/pss_lic keys --ids
   /opt/pss/tools/pss_lic cancel --key-id <id> --out back.r2h
   ```
2. On node **A**, apply the file received and restart the service:

   ```bash
   /opt/pss/tools/pss_lic apply --in back.r2h
   sudo systemctl restart pss
   ```

The `--recipient` option is not valid for `cancel`: the license goes back where it came from. Like `rehost`, the `cancel` command asks for confirmation. `detach` itself does not ask — the transfer is bounded by its period and is reversible.

Guard the intermediate files as carefully as in a permanent transfer: until the H2R has been applied on node B, and the R2H on node A, the license is available on neither and comes back only when the transfer period expires.

## Exit codes

| Code | Meaning |
| --- | --- |
| `0` | The operation succeeded. The same code is returned when the update had already been applied |
| `1` | The protection system refused the operation — the message gives the status number. The same code is returned when the operation ended with no data, for example `the R2H: nothing to write` |
| `2` | A syntax error: an unknown command, an option that is not valid for the command, a missing required option, an invalid value. The same code is returned when the operator answered “no” to the confirmation prompt |
| `3` | An input/output error: the file cannot be opened, read or written |

Two cases are worth allowing for in scripts. An operator declining the confirmation is code `2`, not `0`: a “non-zero code means failure” check will take the cancellation for a fault. An unreadable input file is code `3`, not `1`: it never got as far as the protection system.

```bash
# distinguish a refusal by the key from a bad command line or a missing file
/opt/pss/tools/pss_lic apply --in license.v2c || {
    case $? in
        1) echo "the key refused the update" >&2 ;;
        2) echo "wrong command line, or the operator declined" >&2 ;;
        3) echo "the file could not be read" >&2 ;;
    esac
}
```

## Messages and diagnostics

Messages go to stderr with the `pss_lic:` prefix. A refusal by the protection system is always printed in one shape — what failed, a text description of the reason and the status number — and for the common reasons a hint line is added:

```
pss_lic: reading the key state (C2V) failed: too many keys match the scope (status 37)
pss_lic:   hint: this host holds several keys; run 'pss_lic keys --ids' and pass --key-id
```

The `-q` option removes the success messages — including the warning about writing to the terminal — but not the errors and not the hints. The `-v` option adds a log of the calls to the protection system: the requests, the number of bytes read and written, the name of the function called. When contacting support, attach the output taken with `-v`.

The most frequent group of refusals is the key not being visible or the protection system service not answering (statuses 7, 14, 33, 50 and 80). Check whether the service is running (`systemctl status aksusbd`), whether the USB key is plugged in, and whether the supplier libraries are in place in `/var/hasplm` — they are installed by the **pstreamer** package. The remaining refusals are in the table below; the first column holds the status number from the refusal line, the second its text.

| Status | Refusal text | Cause and remedy |
| --- | --- | --- |
| 37 | `too many keys match the scope` | The node sees several keys. Get the list with `keys --ids` and pass `--key-id` |
| 42 | `License Manager version is too old` | The **aksusbd** version is below 9.12; update the protection system package |
| 47 | `secure storage contains garbage` | The license storage is damaged; a new V2C from the supplier is required |
| 48 | `vendor library cannot be found` | There are no supplier libraries in `/var/hasplm`; they are installed by the **pstreamer** package |
| 54 | `the update is older than the one already installed (stale or rolled-back V2C)` | An outdated V2C is being applied; ask the supplier for a fresh one |
| 55 | `another update must be installed first` | The update file is ahead of the key’s state — an intermediate update was skipped; export a fresh C2V and apply the V2C issued for it |
| 58 | `invalid XML recipient parameter` | The recipient block is corrupted; export it again on the receiving node |
| 60 | `the scope does not select a unique Product` | Check `--product-id`, and on a node with several keys add `--key-id` |
| 61 | `invalid Product information` | Check `--product-id`; for Perfect Streamer it is `2` |
| 62 | `unknown recipient; this blob may only be applied on the recipient it was made for` | The file was issued for another machine and can be applied only there |
| 63 | `invalid duration specified` | The transfer period is longer than the license allows |
| 64 | `cloned secure storage detected` | The license storage has been recognized as a copy — the result of cloning a disk or a virtual machine; ask the supplier to reissue the license for this machine |
| 66 | `the specified key is inactive` | The key is inactive |
| 67 | `no detachable Feature exists` | The temporary transfer is not allowed by the terms of the license |
| 68 | `the scope does not select a unique host` | The node sees several protection system services; `fingerprint` and `recipient` refer to the service, not to the key |
| 69 | `rehost is not allowed for this licence` | The transfer is not allowed by the terms of the license |
| 70 | `the licence was rehosted to another machine` | The key has already been moved off this node |
| 71 | `an old rehost licence is being applied` | An old transfer file is being applied; the key has already been moved off this node |
| 77 | `the recipient of the requested operation is older than expected` | The receiving node runs an outdated protection system service; update it |
| 78 | `secure storage ID mismatch` | The license storage belongs to another machine; a new V2C from the supplier is required |
| 79 | `duplicate host name while the key uses host name fingerprinting` | There is a second node with the same name on the network; rename the node or reissue the license |
| 94 | `the key and the update are out of sync (update counters diverged)` | The update counters of the key and of the file have diverged; export a fresh C2V and apply the V2C issued for it |

For every known status the utility prints a text description; an unrecognized status is printed as `unrecognised status` together with its number.

The `keys` command is a case of its own: if the protection system did not accept the detailed format of the listing, the utility prints the refusal line and then repeats the request in the short format. The listing is produced all the same and the exit code stays zero, so such a refusal line before a normal result should not be read as a failure.

The `version` command works even when the protection system is broken — which is exactly what makes it useful as the first step of diagnosis. It prints the banner of the utility and the API version of the protection system; if the protection system service is unavailable, `unavailable` is printed instead of the version together with a status number, and the exit code stays zero.

## Migrating from version 1.2

In version 2.0 the positional syntax has been replaced by commands and long options; the former forms are not supported. When one is entered, the utility prints its replacement and exits with code `2`.

| In 1.2 | In 2.0 |
| --- | --- |
| `pss_lic u <file>` | `pss_lic apply --in <file>` |
| `pss_lic i [key] [file]` | `pss_lic c2v [--key-id <key>] [--out <file>]` |
| `pss_lic d <product> [file]` | `pss_lic detach --product-id <product> [--out <file>]` |
| `pss_lic r <key> [file]` | `pss_lic rehost --key-id <key> [--out <file>]` |
| `pss_lic f [file]` | `pss_lic fingerprint [--out <file>]` |

The behavior of the output has changed as well: in 2.0 only data goes to stdout and the messages go to stderr. Scripts that parsed the mixed output of version 1.2 have to be corrected.
