More Examples: Talk notes
parent
444d9e87b9
commit
69738c3078
435
slides.org
435
slides.org
|
@ -180,17 +180,17 @@
|
|||
| \_ Again: A Research Task | 0:00:15 | DRAFT | againframe |
|
||||
| \_ A Quick-n-Dirty Solution | 0:01:10 | DRAFT | frame |
|
||||
|-------------------------------------------------------+----------+---------+-------------|
|
||||
| \_ More Examples | | LACKING | |
|
||||
| \_ More Examples | | RAW | |
|
||||
| \_ More Example Topics | | | |
|
||||
| \_ Weather Every 60s | | LACKING | frame |
|
||||
| \_ Resize Images | | LACKING | frame |
|
||||
| \_ Password Generation | | LACKING | frame |
|
||||
| \_ Password Manager | | LACKING | frame |
|
||||
| \_ Remote Password Manager With 2FA | | LACKING | frame |
|
||||
| \_ Taking Screenshots | | LACKING | frame |
|
||||
| \_ Screenshot OCR | | LACKING | frame |
|
||||
| \_ Full Circle | | LACKING | fullframe |
|
||||
| \_ Getting Help | | LACKING | frame |
|
||||
| \_ Weather Every 60s | | RAW | frame |
|
||||
| \_ Resize Images | | RAW | frame |
|
||||
| \_ Password Generation | | RAW | frame |
|
||||
| \_ Password Manager | | RAW | frame |
|
||||
| \_ Remote Password Manager With 2FA | | RAW | frame |
|
||||
| \_ Taking Screenshots | | RAW | frame |
|
||||
| \_ Screenshot OCR | | RAW | frame |
|
||||
| \_ Full Circle | | RAW | fullframe |
|
||||
| \_ Getting Help | | RAW | frame |
|
||||
|-------------------------------------------------------+----------+---------+-------------|
|
||||
| \_ Thank You | 00:00:01 | | fullframe |
|
||||
#+END:
|
||||
|
@ -2584,7 +2584,7 @@ This is certainly an efficient means of communicating with the machine.
|
|||
We've come a long way from using the web browser and a mouse.
|
||||
|
||||
|
||||
** LACKING More Examples
|
||||
** RAW More Examples
|
||||
*** More Example Topics [7/7] :noexport:
|
||||
- [X] Screenshots with =import=.
|
||||
- Including copying to clipboard.
|
||||
|
@ -2601,7 +2601,7 @@ We've come a long way from using the web browser and a mouse.
|
|||
- Use =tesserac= to detect matches from =Ctrl+F=.
|
||||
- [X] Finding documentation with =info= and =man=.
|
||||
|
||||
*** LACKING Weather Every 60s :B_frame:
|
||||
*** RAW Weather Every 60s :B_frame:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: frame
|
||||
:END:
|
||||
|
@ -2619,7 +2619,31 @@ Every 60.0s: weather | grep Temp... Sat Mar 16 23:18:56 2019
|
|||
\_\ /_/
|
||||
#+END_SRC
|
||||
|
||||
*** LACKING Resize Images :B_frame:
|
||||
**** Notes :B_noteNH:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: noteNH
|
||||
:END:
|
||||
|
||||
Now that we've put that research task to rest,
|
||||
let's look at some more diverse examples.
|
||||
|
||||
This one,
|
||||
for example.
|
||||
It uses =watch= to execute a command every sixty seconds.
|
||||
Specifically,
|
||||
it uses =weather= to look up some information about the current weather
|
||||
and grabs the temperature line.
|
||||
=cut= is a command we haven't seen yet---it
|
||||
grabs a field separated by the given delimiter.
|
||||
The line is ``Temperature: temp'',
|
||||
so that has the effect of stripping off the ``temperature:'' prefix.
|
||||
And then figlet is a fun little tool that formats text like ASCII art,
|
||||
with various fonts available.
|
||||
|
||||
Though I shold note that the source that =weather= gets its data from does
|
||||
not update every sixty seconds.
|
||||
|
||||
*** RAW Resize Images :B_frame:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: frame
|
||||
:END:
|
||||
|
@ -2633,7 +2657,26 @@ $ for img in *.png; do
|
|||
$ find . -name '*.png' -exec convert {} -resize 50% sm-{} \;
|
||||
#+END_SRC
|
||||
|
||||
*** LACKING Password Generation :B_frame:
|
||||
**** Notes :B_noteNH:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: noteNH
|
||||
:DURATION: 00:00:35
|
||||
:END:
|
||||
|
||||
This example will be useful to people who have a lot of images that the want
|
||||
to perform an operation on.
|
||||
ImageMagick has a =convert= tool which can do a huge variety of image
|
||||
manipulations that you would expect to have to use, say, GIMP for.
|
||||
In this case,
|
||||
we're just using one of the simples ones to reduce the image size by 50%.
|
||||
|
||||
The first example uses /globbing/ to find all PNG images in the current
|
||||
directory.
|
||||
The second example uses the =find= command and searches all child
|
||||
directories as well.
|
||||
Both examples produce a new set of images prefixed with =sm-=.
|
||||
|
||||
*** RAW Password Generation :B_frame:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: frame
|
||||
:END:
|
||||
|
@ -2652,7 +2695,31 @@ $ cut -f2 eff_large_wordlist.txt \
|
|||
oppressor roman jigsaw unhappy thinning grievance
|
||||
#+END_SRC
|
||||
|
||||
*** LACKING Password Manager :B_frame:
|
||||
**** Notes :B_noteNH:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: noteNH
|
||||
:END:
|
||||
|
||||
How about password generation?
|
||||
=pwgen= is a tool that can generate passwords of various forms.
|
||||
Here we generate a random 32-character password.
|
||||
That type of password is useful if you have a password manager,
|
||||
but it's not useful if you need to memorize it.
|
||||
|
||||
When memorization is needed,
|
||||
a /passphrase/ may be a better option.
|
||||
A common way to generate those is to use a large list of memorable words and
|
||||
choose them /at random/.
|
||||
Diceware is one such system,
|
||||
and the EFF has its own word list.
|
||||
But we don't need physical dice when we can just use =sort= to randomly
|
||||
permute the word list.
|
||||
The EFF recommends taking at least six words,
|
||||
which is what I did here.
|
||||
This one is particularly memorable and morbid-sounding.
|
||||
I'm a little upset that I put it in the slide instead of using it!
|
||||
|
||||
*** RAW Password Manager :B_frame:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: frame
|
||||
:END:
|
||||
|
@ -2677,7 +2744,63 @@ $ gpg --decrypt password-db.gpg \
|
|||
#+END_SRC
|
||||
#+BEAMER: \end{uncoverenv}
|
||||
|
||||
*** LACKING Remote Password Manager With 2FA :B_frame:
|
||||
**** Notes :B_noteNH:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: noteNH
|
||||
:END:
|
||||
|
||||
Speaking of password managers.
|
||||
We can create a pretty decent rather quickly.
|
||||
Let's say we have a password list encrypted using GnuPG,
|
||||
which can be decrypted like so.
|
||||
Each account has a URL,
|
||||
username,
|
||||
and password.
|
||||
|
||||
We pipe the output to =grep= to find the one we're looking for.
|
||||
The caret anchors the match to the beginning of the line.
|
||||
=-A2= instructs =grep= to return the line the matches /and/ the two lines
|
||||
that follow it.
|
||||
We then use =tail= to keep only the last two lines,
|
||||
discarding the URL.
|
||||
|
||||
For each line,
|
||||
we then read the first word into =key= and the rest of the line into
|
||||
=value=.
|
||||
This is where it gets a bit more interesting.
|
||||
We don't want to actually output our password anywhere where others could
|
||||
see it or where it may be vulnerable to a side channel like Van Eck
|
||||
phreaking.
|
||||
Instead,
|
||||
we're going to copy the value to the clipboard.
|
||||
|
||||
But that has its own risks too.
|
||||
What if there's a malicious program monitoring the clipboard for passwords?
|
||||
I used =-l 1= with =xclip=.
|
||||
=-l= stands for ``loop'',
|
||||
which is the number of times to serve paste requests.
|
||||
Normally =xclip= goes into the background and acts as a server.
|
||||
=-quiet= keeps =xclip= in the foreground.
|
||||
So if we see that the script moves on to request pasting the next value
|
||||
before we've actually pasted it,
|
||||
then we'll be made aware that something is wrong and perhaps we should
|
||||
change our account information.
|
||||
|
||||
Another nice consequence is that we can paste the username in a field in the
|
||||
web browser,
|
||||
for example,
|
||||
and then it'll immediately proceed to the next line of the password
|
||||
database and prompt us to paste that.
|
||||
So the first value you paste will be the username,
|
||||
and the second value will be the password.
|
||||
And then the script will exit.
|
||||
Very convenient!
|
||||
|
||||
Since the decrypted data exist only as part of the pipeline,
|
||||
the decrypted passwords are only kept plaintext in memory for the duration
|
||||
of the script.
|
||||
|
||||
*** RAW Remote Password Manager With 2FA :B_frame:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: frame
|
||||
:END:
|
||||
|
@ -2692,7 +2815,58 @@ $ gpg --decrypt password-db.gpg \
|
|||
$ ssh -Y mikegerwitz-pc get-passwd https://foo.com
|
||||
#+END_SRC
|
||||
|
||||
*** LACKING Taking Screenshots :B_frame:
|
||||
**** Notes :B_noteNH:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: noteNH
|
||||
:END:
|
||||
|
||||
But what if you need passwords on multiple devices?
|
||||
Well,
|
||||
then you have to worry about how to keep them in sync.
|
||||
It also means that,
|
||||
if you are travelling and asked to decrypt files on your laptop,
|
||||
for example,
|
||||
you're put in a tough spot.
|
||||
|
||||
Instead,
|
||||
let's make that command line from the previous slide a script called
|
||||
=get-passwd=,
|
||||
and have it take the URL as an argument.
|
||||
We can then access it remotely over SSH.
|
||||
But to have clipboard access,
|
||||
we need to forward our X11 session,
|
||||
which is what =-Y= does.
|
||||
|
||||
But that's still not good enough for me.
|
||||
What if my master password is compromised---the
|
||||
password for my database?
|
||||
I'd rather have two-factor authentication.
|
||||
I symmetrically encrypt my password database using a private key that's
|
||||
stored on my Nitrokey,
|
||||
which is a smart card---keys
|
||||
cannot be extracted from it,
|
||||
unless there's a vulnerabilty of course.
|
||||
To unlock the card,
|
||||
I must enter a PIN.
|
||||
That's both something I know and something I have.
|
||||
If you enter the PIN incorrectly three times,
|
||||
the PIN needs to be reset with an administrative password.
|
||||
If you get that wrong three times,
|
||||
the device bricks itself.
|
||||
And this all works over SSH too.
|
||||
|
||||
Encrypting long-term secrets with asymmetric keys isn't a great idea,
|
||||
so there's a tradeoff.
|
||||
I choose to accept it,
|
||||
because passwords aren't long-term secrets---I
|
||||
can easily change them.
|
||||
But you could easily do both---
|
||||
first require decryption with your smart card and then enter a passphrase
|
||||
for a symmetric key.
|
||||
|
||||
|
||||
|
||||
*** RAW Taking Screenshots :B_frame:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: frame
|
||||
:END:
|
||||
|
@ -2708,7 +2882,36 @@ $ import -pause 5 -window root ss.png
|
|||
import png:- | xclip -i -selection clipboard -t image/png
|
||||
#+END_SRC
|
||||
|
||||
*** LACKING Screenshot OCR :B_frame:
|
||||
**** Notes :B_noteNH:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: noteNH
|
||||
:END:
|
||||
|
||||
Okay,
|
||||
back to something less serious.
|
||||
ImageMagick also comes with a vaguely-named utility called =import=,
|
||||
which can capture images from an X server.
|
||||
Screenshots.
|
||||
|
||||
If you run it with just a filename,
|
||||
then it'll change your cursor to a cross.
|
||||
You can drag to define a rectangular region to copy,
|
||||
or you can just click on a window to take a screenshot of the whole thing.
|
||||
|
||||
The second example pauses for five seconds and then takes a screenshot of
|
||||
the entire X session,
|
||||
which includes all monitors.
|
||||
I used this to take a screenshot of context menus in IceCat,
|
||||
since the first method doesn't work in that case.
|
||||
|
||||
The final example avoids outputting to a file entirely and instead feeds
|
||||
the raw image data to standard out.
|
||||
We then pipe that to =xclip= to copy it to the clipboard.
|
||||
Notice the new =image/png= type there.
|
||||
Now you can paste the image into other programs,
|
||||
like image editors or websites.
|
||||
|
||||
*** RAW Screenshot OCR :B_frame:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: frame
|
||||
:END:
|
||||
|
@ -2748,15 +2951,58 @@ $ xclip -o -selection clipboard -t image/png \
|
|||
#+END_SRC
|
||||
#+BEAMER: \end{onlyenv}
|
||||
|
||||
*** LACKING Full Circle :B_fullframe:
|
||||
**** Notes :B_noteNH:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: noteNH
|
||||
:DURATION: 00:01:10
|
||||
:END:
|
||||
|
||||
But when I was trying to come up with interesting examples for this talk,
|
||||
I wanted to try something I hadn't before.
|
||||
=tesseract= is a free (as in freedom) optical character recognition
|
||||
program.
|
||||
Since =import= lets us select a region of the screen,
|
||||
what if we used that to create a script that runs OCR on whatever we
|
||||
select?
|
||||
And just for fun,
|
||||
what if the translation was presented to us by a cow?
|
||||
|
||||
In this example,
|
||||
I selected the keynote speaker image on the LP2019 website.
|
||||
It worked quite well.
|
||||
|
||||
But a cow isn't practical.
|
||||
Instead,
|
||||
you can imagine maybe binding this to a key combination in your window
|
||||
manager.
|
||||
In that case,
|
||||
maybe it'd be more convenient if it was spoken to you,
|
||||
like the second example.
|
||||
Or maybe copied to your clipboard.
|
||||
|
||||
In the third example,
|
||||
we take an image off of the clipboard,
|
||||
run OCR,
|
||||
and then display the resulting text in a GUI dialog with =zenity=.
|
||||
|
||||
I really like these examples,
|
||||
because to an average user,
|
||||
all of this seems somewhat novel.
|
||||
And yet,
|
||||
it's one of the simplest examples we've done!
|
||||
|
||||
YMMV with tesseract,
|
||||
depending on your settings and training data.
|
||||
|
||||
*** RAW Full Circle :B_fullframe:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: fullframe
|
||||
:END:
|
||||
|
||||
#+BEGIN_SRC sh
|
||||
$ xdotool search --name ' GNU IceCat$' windowactivate --sync \
|
||||
&& xdotool getactivewindow windowsize 1024 600 \
|
||||
key ctrl+t \
|
||||
windowsize 1024 600 \
|
||||
key ctrl+t \
|
||||
&& while read url; do
|
||||
xdotool getactivewindow \
|
||||
key ctrl+l type "$url" \
|
||||
|
@ -2771,28 +3017,161 @@ $ xdotool search --name ' GNU IceCat$' windowactivate --sync \
|
|||
done < url-list | tee results.txt
|
||||
#+END_SRC
|
||||
|
||||
*** LACKING Getting Help :B_frame:
|
||||
**** Notes :B_noteNH:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: noteNH
|
||||
:END:
|
||||
|
||||
Okay,
|
||||
for this final example,
|
||||
I'm going to do something a bit more complex.
|
||||
Please take a few seconds to look at this.
|
||||
<pause>
|
||||
Would anyone like to tell me what you think this command line does?
|
||||
|
||||
<...allocate extra time to this slide...>
|
||||
|
||||
=xdotool= is a swiss army knife of X11 operations.
|
||||
It can find windows,
|
||||
give them focus,
|
||||
send keystrokes,
|
||||
move the mouse,
|
||||
and do many other things.
|
||||
|
||||
The first line here finds the first window ending in ``GNU IceCat'' and
|
||||
gives it focus.
|
||||
=--sync= blocks until that completes so we don't proceed too hastily.
|
||||
We then proceed to resize it to 1024x600,
|
||||
and then open a new tab by sending =Ctrl+T=.
|
||||
|
||||
That's right.
|
||||
We've come full circle back to the web browser.
|
||||
|
||||
We then proceed to read each URL form a file =url-list=,
|
||||
which you can see after =done=.
|
||||
For each URL,
|
||||
we send =Ctrl+L= to give focus to the location bar and then type in the
|
||||
URL.
|
||||
We can't chain any commands in =xdotool= after =type=,
|
||||
which is why we have another invocation to hit =Return=.
|
||||
We then sleep for five seconds to give time to navigate.
|
||||
I use Tor,
|
||||
so latency varies.
|
||||
We then send =Ctrl+F=,
|
||||
wait very briefly to give IceCat time to trigger the find,
|
||||
and then send our string to search for.
|
||||
|
||||
If you remember,
|
||||
I mentioned that part of the problem with the GUI approach is that it
|
||||
requires visual inspection.
|
||||
Fortunately for us,
|
||||
we have =tesseract=!
|
||||
So we take a screenshot of the IceCat window at the offset where the match
|
||||
results are on my system.
|
||||
We pipe that image to =tesseract= and,
|
||||
if it contains the word ``Phrase'',
|
||||
as in ``Phrase not found'',
|
||||
we echo the URL as a non-match.
|
||||
All of this is =tee='d to =results.txt= like before.
|
||||
|
||||
<demo it? FSF laptop likely has abrowser, so some tweaking will be needed.>
|
||||
|
||||
This is /not/ what I had in mind when I talked about melding mind and
|
||||
machine.
|
||||
But this shows that,
|
||||
even with GUIs,
|
||||
we can produce some level of automation using existing tools and a little
|
||||
bit of creativity.
|
||||
Of course,
|
||||
this may not work on your system if you font size is different or because
|
||||
of various other factors;
|
||||
to generalize this,
|
||||
we'd have to get more creative to find the result text.
|
||||
|
||||
It's also worth mentioning that =xdotool= can come in handy for the password
|
||||
manager too---instead
|
||||
of copying to the clipboard,
|
||||
we can type it directly into a window.
|
||||
And by specifying which window to send it to,
|
||||
we can ensure that we don't accidentally type in the wrong window,
|
||||
like a chat,
|
||||
if the user changes focus.
|
||||
That also thwarts systems that implement the terrible anti-pattern of try to
|
||||
prevent you from pasting passwords.
|
||||
|
||||
|
||||
*** RAW Getting Help :B_frame:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: frame
|
||||
:END:
|
||||
|
||||
- All GNU packages have Info manuals
|
||||
- All GNU packages have Info manuals and =--help=
|
||||
- Most programs (including GNU) have manpages
|
||||
|
||||
#+BEAMER: \subskip
|
||||
|
||||
#+BEGIN_SRC sh
|
||||
# manpage for grep
|
||||
$ man grep
|
||||
|
||||
# full manual for grep
|
||||
$ info grep
|
||||
$ grep --help # usage information for grep
|
||||
$ man grep # manpage for grep
|
||||
$ info grep # full manual for grep
|
||||
|
||||
# bash help
|
||||
$ help
|
||||
$ man bash
|
||||
#+END_SRC
|
||||
|
||||
**** Notes :B_noteNH:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: noteNH
|
||||
:DURATION: 00:01:45
|
||||
:END:
|
||||
|
||||
I have presented a lot of stuff here,
|
||||
and I only got to a fraction of what I would have liked to talk about.
|
||||
Some of you watching this aren't familiar with a lot of these topics,
|
||||
or possibly /any/ of them,
|
||||
so getting started may seem like a daunting task.
|
||||
Where do you start?
|
||||
|
||||
As I showed before,
|
||||
the process of writing a command line is an iterative one.
|
||||
Learning is the same way.
|
||||
I don't remember all of the options for these programs.
|
||||
=xdotool= I had used only lightly before this talk,
|
||||
for example;
|
||||
I had to research how to write that command line.
|
||||
But I didn't use the Internet to do it;
|
||||
I did it from the comfort of my terminal using only what was already
|
||||
installed on my system.
|
||||
|
||||
You can usually get usage information for programs by typing =--help= after
|
||||
the command.
|
||||
This will work for all GNU programs,
|
||||
but not all command line programs implement it.
|
||||
=tesseract=, for example, outputs its usage information when you run it with
|
||||
no arguments,
|
||||
but offers no =--help=.
|
||||
All GNU programs also offer Info manuals,
|
||||
which read like books;
|
||||
those can be found with the =info= command,
|
||||
and can also be read in a much better format using Emacs.
|
||||
You can also usually find them online in HTML format.
|
||||
Finally,
|
||||
most command line programs for Unix-like operating systems also include
|
||||
manpages,
|
||||
accessible with the =man= command.
|
||||
If you want to know how to use =man=,
|
||||
you can view its own manpage using =man man=.
|
||||
|
||||
You can also get some help using Bash itself by simply typing =help= to list
|
||||
its builtins,
|
||||
and it has a very comprehensive manpage.
|
||||
|
||||
This is obviously a bit different than how people interact with GUIs,
|
||||
which are designed to be discoverable without the need for users to read
|
||||
documentation.
|
||||
|
||||
|
||||
** Thank You :B_fullframe:
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: fullframe
|
||||
|
|
Loading…
Reference in New Issue