<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

    <title>Yury V. Zaytsev</title>

    <link href="https://yury.zaytsev.net/" />
    <link href="https://yury.zaytsev.net/atom.xml" type="application/atom+xml" rel="self"/>

    <updated>2019-07-28T17:22:29+00:00</updated>
    <id>https://yury.zaytsev.net/</id>
    <author>
        <name>Yury V. Zaytsev</name>
        <email>yury@shurup.com</email>
    </author>

    
    <entry>
        <id>https://yury.zaytsev.net/press/2019/07/28/xquery-saves-life-ikea</id>
        <title>XQuery saves hacker's life while shopping for bedding</title>
        <author>
            <name>Yury V. Zaytsev</name>
            <uri>https://yury.zaytsev.net/</uri>
        </author>
        <link href="https://yury.zaytsev.net/press/2019/07/28/xquery-saves-life-ikea.html" type="text/html" />
        <updated>2019-07-28T00:00:00+00:00</updated>
        <content type="html">&lt;p&gt;A couple of days ago I was confronted with an unpleasant discovery in bed, which once again has made me acutely aware of the frailty of life. Specifically, I was looking at a glaring hole in my soon to be a decade old bed sheets.&lt;/p&gt;

&lt;p&gt;“How annoying!” I thought, being presented with a very tangible physical problem, which cannot be immediately solved with an elegant one-liner shell script… Oh, wait! In this day and age IKEA must assuredly have an online shop, so I could just pick a new set of linen and get it shipped to my doorstep.&lt;/p&gt;

&lt;p&gt;Moreover, in spite of an overwhelming multitude of products available for purchase, one can apply a simple set of criteria, which would invariably lead to an optimal solution to this otherwise &lt;em&gt;NP&lt;/em&gt;-hard problem:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Assuming that the price is still any indicator of quality in our post-modern world, products should be sorted by price, descending&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Products should be filtered by type and grouped by family, allowing for colour and design variations to be easily assessed&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Designs featuring variegated colouring of any kind or anathematic striping patterns should be immediately discarded from consideration&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest should &lt;em&gt;purely&lt;/em&gt; amount to &lt;code class=&quot;highlighter-rouge&quot;&gt;map buy $ take 2 products&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Sure enough, however, this quickly turned out to be one of those brilliant plans that are notoriously easier to verbalise than execute.&lt;/p&gt;

&lt;p&gt;An enterprising adventurer who chances to look for sheets on the &lt;a href=&quot;https://www.ikea.com/de/de/cat/bettwaesche-tl004/&quot;&gt;IKEA website&lt;/a&gt; is immediately confronted with the lack of basic hygiene facilities like sorting by price, not even speaking of filtering by type. The products are displayed in a seemingly random order, which precludes any organised attempts to make sense of what design variations are available for a particular type.&lt;/p&gt;

&lt;p&gt;Fortunately, no amount of corporate cargo-agile website-building idiocy can dissuade a determined hacker on the verge of perdition from buying new bedding. Some way out just has to be out there, has it not?&lt;/p&gt;

&lt;p&gt;They must certainly have an API, which can be queried to obtain a list of products, so that one can hack up a &lt;a href=&quot;http://jmespath.org&quot;&gt;JMESPath&lt;/a&gt; expression and be done with it, right? &lt;strong&gt;Wrong!&lt;/strong&gt; They do have one indeed, but it is one of those special &lt;a href=&quot;https://www.youtube.com/watch?v=wTqsV3q7rRU&quot;&gt;dangerous street APIs&lt;/a&gt; returning pre-rendered HTML snippets, which you are supposed to shove up your DOM.&lt;/p&gt;

&lt;p&gt;Here is the kind of sodomy that one would typically have to deal with:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;product-compact&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;data-ref-id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;10357259&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;data-price=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;11.99&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;data-currency=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EUR&quot;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;product-compact__spacer&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.ikea.com/de/de/p/dvala-bettlaken-weiss-10357259/&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;product-compact__image-container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;product-compact__image&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;range-image-claim-height&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;padding-bottom: 99.95%;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
              &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;IKEA DVALA Bettlaken&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;product-compact__name&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;DVALA&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;product-compact__type&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        Bettlaken,
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;product-compact__description&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;240x260 cm&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;product-compact__price&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;product-compact__price__value&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;11.99&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.ikea.com/de/de/p/dvala-bettlaken-weiss-10357259/&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;product-compact__gpr-disclaimer disclaimer&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          Weitere Farben/ Ausführungen vorhanden
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Challenge accepted!™&lt;/p&gt;

&lt;p&gt;Let us fire up BaseX and &lt;a href=&quot;https://en.wikipedia.org/wiki/Battle_of_the_Neva&quot;&gt;put the impertinent Swedes back in check&lt;/a&gt; by obtaining some actionable insights® from their &lt;del&gt;Big&lt;/del&gt;^WGarbage Data:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;zaytsev:~ zaytsev$&lt;/span&gt; brew cask install adoptopenjdk
&lt;span class=&quot;gp&quot;&gt;zaytsev:~ zaytsev$&lt;/span&gt; brew install basex
&lt;span class=&quot;gp&quot;&gt;zaytsev:~ zaytsev$&lt;/span&gt; basexgui
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hack, hack, hack!&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;declare variable $doc := html:parse(fetch:binary('https://www.ikea.com/de/de/cat/bettwaesche-10651/'));
 
(: declare variable $typeFilter := ''; :)
declare variable $typeFilter := 'Bettwäscheset';
        
declare function local:trim($arg) {
   replace(replace($arg,'\s+$',''),'^\s+','')
};
 
declare function local:parseItem($item) {
  let $cleanName := $item//span[@class='product-compact__name']/text()
  let $cleanTypes := $item//span[@class='product-compact__type']//text() ! local:trim(.)
  let $cleanPrice := $item/@data-price/data()
  let $cleanLink := $item//a[1]/@href/data()
  let $cleanRemarks := $item//span[contains(@class, 'disclaimer')]/text() ! local:trim(.)
  return
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Item&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;Name&amp;gt;&lt;/span&gt;{ $cleanName }&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Name&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;Type&amp;gt;&lt;/span&gt;{ string-join($cleanTypes, ' ') }&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Type&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;Price&amp;gt;&lt;/span&gt;{ $cleanPrice }&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Price&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;Link&amp;gt;&lt;/span&gt;{ $cleanLink }&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Link&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;Remarks&amp;gt;&lt;/span&gt;{ $cleanRemarks }&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Remarks&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Item&amp;gt;&lt;/span&gt;
};

let $items := $doc//div[@class='product-compact']
let $results := 
  for $item in $items
  let $data := local:parseItem($item)
  where contains($data/Type, $typeFilter)
  order by number($data/Price) descending
  group by $name := $data/Name
  return
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Product&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{ $name }&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;variants=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{ count($data) }&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{
      for $variant in $data
      order by number($variant/Price) descending
      return &lt;span class=&quot;nt&quot;&gt;&amp;lt;Variant&amp;gt;&lt;/span&gt;{ $variant/node()[not(name(.)='Name')] }&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Variant&amp;gt;&lt;/span&gt;
    }&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Product&amp;gt;&lt;/span&gt;
return
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Results&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;filtered-products=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{ count($results) }&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;filtered-items=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{ count($results//Variant) }&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;total-items=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{ count($items) }&quot;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Types&amp;gt;&lt;/span&gt;{
      for $type in distinct-values($results//Type)
      order by $type
      return &lt;span class=&quot;nt&quot;&gt;&amp;lt;Type&amp;gt;&lt;/span&gt;{ $type }&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Type&amp;gt;&lt;/span&gt;
    }&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Types&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Products&amp;gt;&lt;/span&gt;{ $results }&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Products&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Results&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, this starts making some sense, yay!&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Results&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;filtered-products=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;12&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;filtered-items=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;22&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;total-items=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;24&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Types&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Type&amp;gt;&lt;/span&gt;Bettwäscheset, 2-teilig, 140x200/80x80 cm&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Type&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Type&amp;gt;&lt;/span&gt;Bettwäscheset, 2-teilig, 155x220/80x80 cm&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Type&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Type&amp;gt;&lt;/span&gt;Bettwäscheset, 3-teilig, 240x220/80x80 cm&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Type&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Types&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Products&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Product&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;PUDERVIVA&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;variants=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;Variant&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Type&amp;gt;&lt;/span&gt;Bettwäscheset, 2-teilig, 155x220/80x80 cm&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Type&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Price&amp;gt;&lt;/span&gt;59.99&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Price&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Link&amp;gt;&lt;/span&gt;https://www.ikea.com/de/de/p/puderviva-bettwaescheset-2-teilig-hellgelb-80431595/&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Link&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Remarks&amp;gt;&lt;/span&gt;Weitere Farben/ Ausführungen vorhanden&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Remarks&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Variant&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Product&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Product&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;SÄCKBUSKE&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;variants=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;4&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;Variant&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Type&amp;gt;&lt;/span&gt;Bettwäscheset, 2-teilig, 155x220/80x80 cm&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Type&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Price&amp;gt;&lt;/span&gt;49.99&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Price&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Link&amp;gt;&lt;/span&gt;https://www.ikea.com/de/de/p/saeckbuske-bettwaescheset-2-teilig-grau-00448397/&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Link&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Remarks&amp;gt;&lt;/span&gt;Weitere Farben/ Ausführungen vorhanden&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Remarks&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Variant&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Products&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Results&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After dumping the whole DOM to file and some more fiddling with XQuery, the fog of war finally starts clearing up!&lt;/p&gt;

&lt;p&gt;By now it is pretty obvious that I need a PUDERVIVA or SÖMNTUTA (actually, one of each to be on the safe side), as well as one SÄCKBUSKE to match PUDERVIVA with a backup BRUNKRISSLA to match SÖMNTUTA.&lt;/p&gt;

&lt;p&gt;Relieved by the situation returning under control, let us apply the same procedure to other kinds of household textiles. How about buying a bunch of BINNAN towels as well while we are at it?&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I am very impressed by the fact that although the same results could have been achieved by hacking together a throw-away Python script leveraging &lt;code class=&quot;highlighter-rouge&quot;&gt;lxml&lt;/code&gt;, in this case, it is pretty clear indeed, that nothing matches the fun, power and elegance of XQuery.&lt;/p&gt;

&lt;p&gt;Thanks to Hans-Jürgen Rennau for giving me a glimpse into this   wondrous world years aback!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <id>https://yury.zaytsev.net/press/2011/06/07/minimum-io-size-and-buggy-firmware</id>
        <title>Who framed mkfs?</title>
        <author>
            <name>Yury V. Zaytsev</name>
            <uri>https://yury.zaytsev.net/</uri>
        </author>
        <link href="https://yury.zaytsev.net/press/2011/06/07/minimum-io-size-and-buggy-firmware.html" type="text/html" />
        <updated>2011-06-07T00:00:00+00:00</updated>
        <content type="html">&lt;h2 id=&quot;io-limits-quest-for-increased-drive-capacity&quot;&gt;I/O Limits: Quest for increased drive capacity&lt;/h2&gt;

&lt;p&gt;My first Armstrad had a glorious 20M hard drive and now I sometimes feel dissatisfied about the capacity of a shiny new 2T RAID array. Some &lt;em&gt;1 000 000x&lt;/em&gt; increase in 15 years, in fact, does not that sound quite amazing when one thinks about it?&lt;/p&gt;

&lt;p&gt;The storage devices used to expose the data in 512B large addressable blocks to the OS. However, as their capacity has been steadily increasing, it became clear that the overhead associated with each sector on the current 512 byte sector disks is becoming a limiting factor.&lt;/p&gt;

&lt;p&gt;In the reality, apart from 512 bytes worth of data, each physical sector contains quite a bit of extra information, such as an error correction checksum, sync label, etc. In some cases, these overheads amounted up to 15% of the usable storage space. For reasonably large drives of 2T and more we might be speaking about some 300G lost due to the layout format inefficiency.&lt;/p&gt;

&lt;p&gt;Therefore, as storage vendors quickly realized, one way to obtain a major increase in capacity is to reduce the overheads associated with storing each physical sector on disk. That is why most of the modern hard drives operate with 4K sectors internally (&lt;code class=&quot;highlighter-rouge&quot;&gt;physical_block_size&lt;/code&gt;), while exposing 512B sectors (&lt;code class=&quot;highlighter-rouge&quot;&gt;logical_block_size&lt;/code&gt;) to legacy software.&lt;/p&gt;

&lt;p&gt;However, this trickery soon enough led another annoying problem: because the software layer on top of the drive’s firmware is still thinking that it operates with 512B sectors internally, it could easily happen that larger logical blocks in use by the file system would become mis-aligned against physical 4K sectors that the drive is dealing with internally.&lt;/p&gt;

&lt;p&gt;In such a case each unaligned I/O operation requested by the OS would cause the drive to perform a Read-Modify-Write (RMW) highly impacting the performance by reducing IOPS and increasing the latency. RMWs can be to a certain extent mitigated in firmware, but the drive just does not have enough information about the real needs of the OS to completely eliminate the problem.&lt;/p&gt;

&lt;p&gt;That is why it has been finally agreed, that instead of building error-prone and extremely complicated kludges into the firmware, it makes much more sense to expose the information about the preferred sector sizes and alignment to the OS and propagate it to the upper layers such that partitioning, file system creation tools, etc. would be aware of it.&lt;/p&gt;

&lt;p&gt;One way or another, the Linux I/O stack (starting from Linux &amp;gt;= 2.6.31) has been enhanced to consume vendor-provided information about the I/O limits &lt;a href=&quot;http://people.redhat.com/msnitzer/docs/io-limits.txt&quot; title=&quot;I/O Limits: block sizes, alignment and I/O hints&quot;&gt;ms-1&lt;/a&gt; that allows Linux tools (parted, lvm, mkfs.*, etc.) to optimize the placement of and access to the data (see also &lt;a href=&quot;http://people.redhat.com/msnitzer/docs/&quot; title=&quot;Home page of Mike Snitzer, Red Hat&quot;&gt;ms-2&lt;/a&gt; for other very interesting documents regarding this issue). Also, be sure to check out a very interesting article by Tejun Heo &lt;a href=&quot;https://ata.wiki.kernel.org/index.php/ATA_4_KiB_sector_issues&quot; title=&quot;ATA pages @ kernel.org wiki&quot;&gt;ko&lt;/a&gt; regarding the sector size issues in general (thanks to Slyfox for the link).&lt;/p&gt;

&lt;h2 id=&quot;the-buggy-ssd-firmware-vs-minimum_io_size&quot;&gt;The buggy SSD firmware vs. minimum_io_size&lt;/h2&gt;

&lt;p&gt;Now, on the practical side, even though RHEL6.1, for instance, has a complete support for I/O limits, not all devices (especially the legacy ones) actually provide this information to the kernel.&lt;/p&gt;

&lt;p&gt;Even worse, some of them, e.g. an incredible Samsung SS805 SSD drive with firmware version &lt;code class=&quot;highlighter-rouge&quot;&gt;AD3Q&lt;/code&gt; (MCCOE1HG5MXP-0VBD3-0H2) which I was lucky enough to own, are broken enough to deliberately report &lt;em&gt;wrong&lt;/em&gt; information about &lt;code class=&quot;highlighter-rouge&quot;&gt;physical_block_size&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;logical_block_size&lt;/code&gt; and most importantly &lt;code class=&quot;highlighter-rouge&quot;&gt;minimum_io_size&lt;/code&gt; to the OS (this particular drive reported 8912 bytes as the &lt;code class=&quot;highlighter-rouge&quot;&gt;minimum_io_size&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Therefore, it is not surprising at all, that right after partitioning the disk and formating the partitions, the installation program refused to mount the newly created file systems. At the first sight, of course, the OS, and more specifically &lt;code class=&quot;highlighter-rouge&quot;&gt;mkfs&lt;/code&gt; were to get the blame. How come it creates file systems that are so broken that they can not be even mounted?&lt;/p&gt;

&lt;p&gt;A more careful investigation revealed, however, that &lt;code class=&quot;highlighter-rouge&quot;&gt;mkfs&lt;/code&gt; is just doing its job: the underlying &lt;code class=&quot;highlighter-rouge&quot;&gt;minimum_io_size&lt;/code&gt; hint (8K) gets propagated upwards and so it creates a file system with a 8K block size without hesitation.&lt;/p&gt;

&lt;p&gt;However, in order for &lt;code class=&quot;highlighter-rouge&quot;&gt;mount&lt;/code&gt; to be able to mount the file system, the block size should be &amp;lt;= kernel page size (which is 4K on x86_64 under normal conditions) &lt;a href=&quot;http://lkml.org/lkml/2006/9/8/4&quot;&gt;lkml-1&lt;/a&gt;. Hence, the file system can be created, but not used.&lt;/p&gt;

&lt;p&gt;Now that this has been figured out, all it takes is to find a firmware update to version &lt;code class=&quot;highlighter-rouge&quot;&gt;CD3Q&lt;/code&gt; and magically all is well again… However, if you haven’t been previously exposed to I/O limits-related issues, would you be able to make any sense out of the mysterious &lt;code class=&quot;highlighter-rouge&quot;&gt;EXT4-fs: bad block size 8192&lt;/code&gt; messages in &lt;code class=&quot;highlighter-rouge&quot;&gt;dmesg&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;As an exercise for the readers, now forget everything that you have recollected so far and try to read the post backwards… and remember, winners never cheat, and cheaters never win!&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <id>https://yury.zaytsev.net/press/2011/06/04/dell-poweredge-r710-firmware</id>
        <title>Updating firmware on Dell PowerEdge R710</title>
        <author>
            <name>Yury V. Zaytsev</name>
            <uri>https://yury.zaytsev.net/</uri>
        </author>
        <link href="https://yury.zaytsev.net/press/2011/06/04/dell-poweredge-r710-firmware.html" type="text/html" />
        <updated>2011-06-04T00:00:00+00:00</updated>
        <content type="html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Updating firmware used to be an uncomplicated, albeit slightly dangerous process. Unfortunately, as the server hardware developed over time, it did not become any simpler, but rather evolved into even more of an arcane rite.&lt;/p&gt;

&lt;p&gt;Moreover, it seems that there is no comprehensive checklist regarding the firmware updates of the Dell PowerEdge server family and the information is spread over the support forums, tech wikis and miscellaneous blogs. Hence, this compilation was created in a hope that it will be useful and save time to some.&lt;/p&gt;

&lt;p&gt;Let us consider a case of a Dell PowerEdge R710 featuring 2 x 2T hard drives and a 100G solid state drive, equipped with an iDRAC 6 Enterprise remote access card. There are generally several avenues that one might take to update the server firmware:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;iDRAC firmware update facility (limited to the firmware of the DRAC itself and the USC, Dell Universal Server Configurator / Lifecycle Controller &lt;a href=&quot;http://support.dell.com/support/edocs/software/smusc/&quot;&gt;dell-1&lt;/a&gt;), which requires manually downloaded firmware update (or repair) packages&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Dell USC / LC, which is an UEFI based software that is able to update almost all firmwares of the devices that are present in the server using a number of possible sources of updates:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;Dell FTP site &lt;a href=&quot;ftp://ftp.dell.com&quot;&gt;dell-2&lt;/a&gt;, in which case at least one of the network interface cards present in the system has to be configured from within USC, so that the server would be able to access external resources directly or via a proxy server&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Special USB media prepared beforehand using a software called Dell Repository Manager &lt;a href=&quot;http://support.dell.com/support/edocs/SOFTWARE/smdrm/&quot;&gt;dell-3&lt;/a&gt;, which needs to be deployed to a Windows management PC&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Dell OpenManage Server Update Utility &lt;a href=&quot;http://support.dell.com/support/edocs/software/smsuu/&quot;&gt;dell-4&lt;/a&gt;, which is a DVD image containing a comprehensive collection of firmware updates; in some sense, the USB media produced by the Repository Manager are subsets of SUU specific to each particular server&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Dell Systems Management Tools and Documentation all-in-one DVD &lt;a href=&quot;http://support.dell.com/support/edocs/software/smsom/&quot;&gt;dell-5&lt;/a&gt;, which contains the whole suite of OpenManage-branded Dell systems management software (OMSA, SBUU, SSDT and ITA)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Dell Update Packages (DUPs), which are accessible from the download pages for each specific Dell server &lt;a href=&quot;http://support.dell.com/&quot;&gt;dell-6&lt;/a&gt;; the right download page can be found by entering the service tag (unique server family identifier, which can be found in the DRAC interface or USC among other sources)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A rather complete (but possibly not exhaustive) list of components that might require updates is as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;iDRAC card&lt;/li&gt;
  &lt;li&gt;Dell BIOS&lt;/li&gt;
  &lt;li&gt;Dell USC / LC&lt;/li&gt;
  &lt;li&gt;Dell OS Drivers pack (part of LC)&lt;/li&gt;
  &lt;li&gt;Dell 32-bit Diagnostics software (part of LC)&lt;/li&gt;
  &lt;li&gt;Dell-branded RAID controllers, i.e. PERC H200I&lt;/li&gt;
  &lt;li&gt;Network interface cards&lt;/li&gt;
  &lt;li&gt;SSD devices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What follows are comments regarding each one of those and applicable update methods.&lt;/p&gt;

&lt;h2 id=&quot;possible-firmware-update-procedures&quot;&gt;Possible firmware update procedures&lt;/h2&gt;

&lt;h3 id=&quot;idrac-firmware-update&quot;&gt;iDRAC firmware update&lt;/h3&gt;

&lt;p&gt;Updating the DRAC firmware should be the first step to updating anything else, especially in the case of a restricted onsite presence / remote hands availability. During the update, the DRAC might become unavailable for a period of time up to 15 minutes; this is normal and expected.&lt;/p&gt;

&lt;p&gt;It is preferable to turn off the server and perform the update from the DRAC management console (iDRAC Settings → Update → Upload). The update package has to be downloaded manually from the server support and drivers home page at Dell.&lt;/p&gt;

&lt;p&gt;Additionally, iDRAC is able to re-flash USC / LC using USC repair packages &lt;a href=&quot;ftp://ftp.dell.com/LifecycleController/&quot;&gt;lc-1&lt;/a&gt; in the case if it was hosed during the update. It is generally not recommended by Dell and considered to be a last-resort action, but I have found it to be the only reliable way of updating the USC.&lt;/p&gt;

&lt;h3 id=&quot;dell-usc--lc-platform-update&quot;&gt;Dell USC / LC Platform Update&lt;/h3&gt;

&lt;p&gt;This was found to be the most reliable and complete procedure to update most of the firmwares in the system. In order to perform such an update, one needs to enter the “System Services” menu on boot (F10).&lt;/p&gt;

&lt;p&gt;Once USC is loaded, the Platform Update can be launched. It is recommended to first update all of the suggested firmwares and then again launch Platform Update to update USC itself separately, because it was found to be the less reliable update of all.&lt;/p&gt;

&lt;p&gt;Sometimes, the USC will get stuck after update and the server will keep displaying “Entering USC…” message for hours (everything below 20 minutes might still be fine). In this case, USC can be restored via iDRAC as described above.&lt;/p&gt;

&lt;p&gt;Unfortunately, it took a lot of experimentation to find out that this particular server will not handle anything older or newer, but USC 1.3. There is no scientific explanation for that up to now, because generally in such a case Dell just replaces the motherboard without going on into the details of what exactly went wrong.&lt;/p&gt;

&lt;h3 id=&quot;dell-systems-management-tools-and-documentation&quot;&gt;Dell Systems Management Tools and Documentation&lt;/h3&gt;

&lt;p&gt;Using this DVD instead of downloading the tools separately is important, because the SMTD DVD is bootable, unlike those on which the rest of the tools are distributed, where one is expected to prepare bootable disks oneself.&lt;/p&gt;

&lt;p&gt;The process is rather trivial: one needs to boot off the DVD and launch the platform update process. The update program will request the DVD to be replaced with SUU DVD or another media containing the update repository.&lt;/p&gt;

&lt;p&gt;It is worth to note, that SUU generally contains most outdated firmware out there, so many updates might just not be available if one goes down this route.&lt;/p&gt;

&lt;h3 id=&quot;dell-update-packages&quot;&gt;Dell Update Packages&lt;/h3&gt;

&lt;p&gt;DUPs are listed last, because they are expected to be run from a production operating system. Some DUPs, however, contain an ISO generator to create a bootable image which does not require an operating system to be installed, but it is not always the case.&lt;/p&gt;

&lt;p&gt;Dell normally provides DUPs on the server support pages for Windows and Linux or upon request. There is a community-supported repository &lt;a href=&quot;http://linux.dell.com/wiki/index.php/Repository&quot;&gt;dell-linux&lt;/a&gt; with DUPs wrapped around with native Linux packages, however, it is not officially endorsed or supported.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;It is worth to note, that some updates (even critical ones!) are only available in form of DUPs, i.e. for the SSD devices and not even referenced from server support pages. In such cases, one needs to search Dell support website &lt;a href=&quot;http://support.dell.com/&quot;&gt;dell-support&lt;/a&gt; using the model or serial number as the keyword.&lt;/p&gt;

&lt;p&gt;These updates are not to be neglected as for instance a recent critical SSD update was to fix the minimum advertised I/O block size.&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <id>https://yury.zaytsev.net/press/2011/05/19/sftp-only-users-on-rhel-centos-5</id>
        <title>Setting up SFTP-only users on RHEL/CentOS 5</title>
        <author>
            <name>Yury V. Zaytsev</name>
            <uri>https://yury.zaytsev.net/</uri>
        </author>
        <link href="https://yury.zaytsev.net/press/2011/05/19/sftp-only-users-on-rhel-centos-5.html" type="text/html" />
        <updated>2011-05-19T00:00:00+00:00</updated>
        <content type="html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Normally, when a user account is created on a Unix system, the user in question can log into the system via &lt;code class=&quot;highlighter-rouge&quot;&gt;ssh&lt;/code&gt;, forward TCP ports and use the SFTP subsystem if it is enabled in the server configuration. However, at some point, a sysadmin might face the need to create SFTP-only accounts for a number of users.&lt;/p&gt;

&lt;p&gt;A naïve approach would involve creating a new user and setting his or her shell to &lt;code class=&quot;highlighter-rouge&quot;&gt;/sbin/nologin&lt;/code&gt;. This solution, nevertheless, has two annoying downsides, which might ruin the security of the system, if the users are not trusted enough.&lt;/p&gt;

&lt;p&gt;The first one is that the users would still be able to forward ports if this is globally enabled for the trusted user accounts (which includes &lt;code class=&quot;highlighter-rouge&quot;&gt;sshd&lt;/code&gt; acting as a SOCKS proxy) and the second one is that the users would be able to lurk around the root file system, which certainly cannot be considered as an advantage when the users are not reliable enough.&lt;/p&gt;

&lt;p&gt;In order to solve the first problem, one would need to apply certain configuration parameters to a specific subset of user accounts. The second issue can be avoided by instructing the SSH server to &lt;code class=&quot;highlighter-rouge&quot;&gt;chroot&lt;/code&gt; into the user’s directory upon successful login.&lt;/p&gt;

&lt;p&gt;One can conveniently apply a bunch of configuration options to specific accounts using the &lt;code class=&quot;highlighter-rouge&quot;&gt;Match&lt;/code&gt; directive available in the latest versions of the OpenSSH server:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Match user badguy
    AllowTcpForwarding no
    X11Forwarding no
    ChrootDirectory /srv/sftp
    ForceCommand internal-sftp
    
Match group sftponly
    ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, this directive is only included in OpenSSH 5.x and above, whereas Red Hat Enterprise Linux 5 ships with OpenSSH 4.x. Therefore, an alternative approach will be outlined below.&lt;/p&gt;

&lt;p&gt;In what concerns the chrooting, it can be achieved using the &lt;code class=&quot;highlighter-rouge&quot;&gt;ChrootDirectory&lt;/code&gt; directive. Thankfully, corresponding patches have been backported to OpenSSH 4.x by Red Hat engineers.&lt;/p&gt;

&lt;p&gt;Strictly speaking, it unnecessary to build a proper chroot for SFTP-only users, since OpenSSH includes a built-in SFTP implementation that does not depend upon any external libraries, but if one wants the users to be politely rejected when they try to connect via plain &lt;code class=&quot;highlighter-rouge&quot;&gt;ssh&lt;/code&gt;, one could just make &lt;code class=&quot;highlighter-rouge&quot;&gt;/sbin/nologin&lt;/code&gt; work and that is it.&lt;/p&gt;

&lt;p&gt;N.B.: Red Hat Enterprise Linux 6 ships a newer OpenSSH version that fully supports the &lt;code class=&quot;highlighter-rouge&quot;&gt;Match&lt;/code&gt; directive. This means that for RHEL 6 this tutorial would boil down to the configuration snippet for &lt;code class=&quot;highlighter-rouge&quot;&gt;sshd_config&lt;/code&gt; presented above. Setting up a parallel running SFTP-only &lt;code class=&quot;highlighter-rouge&quot;&gt;sshd&lt;/code&gt; instance is unnecessary. However, one might still wish to skim through the article for the advice on how to create a proper chroot and read the remarks in the Conclusion.&lt;/p&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;h3 id=&quot;setting-up-a-parallel-sftp-only-sshd-instance&quot;&gt;Setting up a parallel SFTP-only &lt;code class=&quot;highlighter-rouge&quot;&gt;sshd&lt;/code&gt; instance&lt;/h3&gt;

&lt;p&gt;Since &lt;code class=&quot;highlighter-rouge&quot;&gt;Match&lt;/code&gt; directive is unavailable and the installation of extra unsupported software is to be avoided at all costs, one can bring up a parallel SFTP-only &lt;code class=&quot;highlighter-rouge&quot;&gt;sshd&lt;/code&gt; instance. The proper way to go would be, of course, to create an extra RPM, i.e. openssh-sftp which installs an additional &lt;code class=&quot;highlighter-rouge&quot;&gt;init&lt;/code&gt; script and symlinks, but for an one-time deployment this might be an overkill.&lt;/p&gt;

&lt;p&gt;First, let us create an &lt;code class=&quot;highlighter-rouge&quot;&gt;init&lt;/code&gt; script, which is a straightforward modification of the stock &lt;code class=&quot;highlighter-rouge&quot;&gt;init&lt;/code&gt; script supplied by Red Hat:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /etc/rc.d/init.d/sshd-sftponly
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;/bin/bash
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; Init file &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;SFTP-only OpenSSH server daemon
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; chkconfig: 2345 55 25
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; description: SFTP-only OpenSSH server daemon
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; processname: sshd-sftponly
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; config: /etc/ssh/ssh_host_key
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; config: /etc/ssh/ssh_host_key.pub
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; config: /etc/ssh/ssh_random_seed
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; config: /etc/ssh/sshd_config-sftponly
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; pidfile: /var/run/sshd-sftponly.pid
&lt;span class=&quot;go&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;library
&lt;span class=&quot;go&quot;&gt;. /etc/rc.d/init.d/functions

RETVAL=0
prog=&quot;sshd-sftponly&quot;

&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; Some functions to make the below more readable
&lt;span class=&quot;go&quot;&gt;SSHD=/usr/sbin/sshd-sftponly
PID_FILE=/var/run/sshd-sftponly.pid

&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; ZYV
&lt;span class=&quot;go&quot;&gt;LOCK_FILE=/var/lock/subsys/sshd-sftponly
OPTIONS=&quot; -f /etc/ssh/sshd_config-sftponly &quot;

&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;runlevel=$&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;runlevel&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;echo &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;$#&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;
start()
{
    cp -af /etc/localtime /var/empty/sshd/etc

&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;    echo -n $&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Starting &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$prog&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;    $&lt;/span&gt;SSHD &lt;span class=&quot;nv&quot;&gt;$OPTIONS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; success &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; failure
&lt;span class=&quot;gp&quot;&gt;    RETVAL=$&lt;/span&gt;?
&lt;span class=&quot;gp&quot;&gt;    [ &quot;$&lt;/span&gt;RETVAL&lt;span class=&quot;s2&quot;&gt;&quot; = 0 ] &amp;amp;&amp;amp; touch &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$LOCK_FILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;    echo
}

stop()
{
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;    echo -n $&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Stopping &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$prog&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;    if [ -n &quot;`pidfileofproc $&lt;/span&gt;SSHD&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; ] ; then
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        killproc $&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;SSHD
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;    else
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        failure $&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Stopping &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$prog&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    fi
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;    RETVAL=$&lt;/span&gt;?
&lt;span class=&quot;gp&quot;&gt;    #&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;we are &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;halt or reboot runlevel &lt;span class=&quot;nb&quot;&gt;kill &lt;/span&gt;all running sessions
&lt;span class=&quot;gp&quot;&gt;    #&lt;/span&gt; so the TCP connections are closed cleanly
&lt;span class=&quot;gp&quot;&gt;    if [ &quot;x$&lt;/span&gt;runlevel&lt;span class=&quot;s2&quot;&gt;&quot; = x0 -o &quot;&lt;/span&gt;x&lt;span class=&quot;nv&quot;&gt;$runlevel&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; = x6 ] ; then
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        killall $&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;prog 2&amp;gt;/dev/null
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;    fi
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;    [ &quot;$&lt;/span&gt;RETVAL&lt;span class=&quot;s2&quot;&gt;&quot; = 0 ] &amp;amp;&amp;amp; rm -f &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$LOCK_FILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;    echo
}

reload()
{
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;    echo -n $&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Reloading &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$prog&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;    if [ -n &quot;`pidfileofproc $&lt;/span&gt;SSHD&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; ] ; then
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        killproc $&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;SSHD -HUP
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;    else
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        failure $&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Reloading &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$prog&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    fi
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;    RETVAL=$&lt;/span&gt;?
&lt;span class=&quot;go&quot;&gt;    echo
}

&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;case &quot;$&lt;/span&gt;1&lt;span class=&quot;s2&quot;&gt;&quot; in
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;    start)
        start
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        ;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    stop)
        stop
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        ;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    restart)
        stop
        start
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        ;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    reload)
        reload
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        ;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    condrestart)
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        if [ -f $&lt;/span&gt;LOCK_FILE &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;            stop
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;            #&lt;/span&gt; avoid race
&lt;span class=&quot;go&quot;&gt;            sleep 3
            start
        fi
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        ;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    status)
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        status -p $&lt;/span&gt;PID_FILE openssh-daemon
&lt;span class=&quot;gp&quot;&gt;        RETVAL=$&lt;/span&gt;?
&lt;span class=&quot;gp&quot;&gt;        ;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    *)
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;        echo $&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Usage: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; {start|stop|restart|reload|condrestart|status}&quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;        RETVAL=1
esac
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;exit $&lt;/span&gt;RETVAL
&lt;span class=&quot;go&quot;&gt;
CTRL+D
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The configuration file would look as follows (not all directives are necessary, take into account the defaults of the distribution in use):&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /etc/ssh/sshd_config-sftponly
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; ZYV
&lt;span class=&quot;go&quot;&gt;PasswordAuthentication no
PermitRootLogin no
PidFile /var/run/sshd-sftponly.pid
Port 2234
Protocol 2
UsePAM no

Subsystem       sftp    internal-sftp

ChrootDirectory /srv/sftp
AllowTcpForwarding no
X11Forwarding no
ForceCommand internal-sftp

CTRL+D
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is important to turn off the use of PAM for authentication in which case &lt;code class=&quot;highlighter-rouge&quot;&gt;sshd-sftponly&lt;/code&gt; will fall back to reading &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/passwd&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/shadow&lt;/code&gt;, instead of using the pluggable authentication module definitions for authentication sources and methods. Otherwise, one would need to provide an additional PAM configuration file basing upon &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/pam.d/sshd&lt;/code&gt; as a template for &lt;code class=&quot;highlighter-rouge&quot;&gt;sshd-sftponly&lt;/code&gt;, however, it is clearly an overkill if no advanced authentication scheme (e.g. against LDAP) is required.&lt;/p&gt;

&lt;p&gt;Then, one needs to create a link to the &lt;code class=&quot;highlighter-rouge&quot;&gt;sshd&lt;/code&gt; binary, register and start the service:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; ln &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/sbin/sshd /usr/sbin/sshd-sftponly
&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; chkconfig &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; sshd-sftponly
&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; service sshd-sftponly start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;creating-an-sftp-only-user&quot;&gt;Creating an SFTP-only user&lt;/h3&gt;

&lt;p&gt;The next task would be to create a group for SFTP-only users and the users themselves:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; groupadd sftponly
&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; useradd badguy &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; sftponly &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /sbin/nologin &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-K&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;UMASK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0022
&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; passwd badguy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here &lt;code class=&quot;highlighter-rouge&quot;&gt;-g&lt;/code&gt; specifies the main group, &lt;code class=&quot;highlighter-rouge&quot;&gt;-s&lt;/code&gt; sets the shell, &lt;code class=&quot;highlighter-rouge&quot;&gt;-m&lt;/code&gt; creates the home directory from a skeleton and &lt;code class=&quot;highlighter-rouge&quot;&gt;-K&lt;/code&gt; overrides the default options with regards to &lt;code class=&quot;highlighter-rouge&quot;&gt;umask&lt;/code&gt; (optional).&lt;/p&gt;

&lt;p&gt;It is important to set a strong password for the user (which can be immediately discarded) even though the public key authentication is to be used, because otherwise the system would consider this account to be inactive.&lt;/p&gt;

&lt;p&gt;Now it is necessary to set up the public key authentication:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;badguy@foo:~$&lt;/span&gt; ssh-keygen &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; rsa &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; 4096
&lt;span class=&quot;go&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; mkdir /home/badguy/.ssh
&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; chmod 700 /home/badguy/.ssh
&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /home/badguy/.ssh/authorized_keys
&lt;span class=&quot;c&quot;&gt;...
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;CTRL+D

&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; chmod 600 /home/badguy/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;creating-a-proper-chroot&quot;&gt;Creating a proper chroot&lt;/h3&gt;

&lt;p&gt;In order to avoid potential privilege escalation, the chroot and all path components leading up to the chroot have to be owned and only writable by &lt;code class=&quot;highlighter-rouge&quot;&gt;root&lt;/code&gt;. Additionally, it is necessary to hardlink the shell and some supporting libraries inside the chroot:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; mkdir &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /srv/sftp/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;home,lib,sbin&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; mkdir /srv/sftp/home/badguy
&lt;span class=&quot;go&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; chown badguy:sftponly /srv/sftp/home/badguy
&lt;span class=&quot;go&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; ln /lib/ld-2.5.so /srv/sftp/lib
&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; ln /lib/ld-linux.so.2 /srv/sftp/lib
&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; ln /lib/libc-2.5.so /srv/sftp/lib
&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; ln /lib/libc.so.6 /srv/sftp/lib
&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; ln /sbin/nologin /srv/sftp/sbin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Luckily, the OpenSSH server will not allow to use a chroot with wrong permissions.&lt;/p&gt;

&lt;h3 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h3&gt;

&lt;p&gt;Now it is time to set up a new host entry and try it out:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;badguy@foo:~$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.ssh/config
&lt;span class=&quot;go&quot;&gt;
Host box
  HostName box.com
  Compression yes
  IdentityFile ~/.ssh/id_rsa
  Port 2234
  User badguy

CTRL+D

&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;badguy@foo:~$&lt;/span&gt; sftp box
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now all these amazing feats would be for nothing if one would not tell the standard &lt;code class=&quot;highlighter-rouge&quot;&gt;sshd&lt;/code&gt; daemon to deny connections for SFTP-only users and it would happily let them in:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/ssh/sshd_config
&lt;span class=&quot;go&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; ZYV
&lt;span class=&quot;go&quot;&gt;DenyGroups sftponly

CTRL+D

&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;root@box #&lt;/span&gt; service sshd restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;There are few additional notes, that I would like to make before closing the article.&lt;/p&gt;

&lt;p&gt;First, if you would like to test SFTP access, you need to use &lt;code class=&quot;highlighter-rouge&quot;&gt;sftp&lt;/code&gt; program as opposed to &lt;code class=&quot;highlighter-rouge&quot;&gt;scp&lt;/code&gt;. It came as a surprise to me (which probably reflects one of the gaps in my knowledge due to me being an autodidact), but the widely used &lt;code class=&quot;highlighter-rouge&quot;&gt;scp&lt;/code&gt; program as opposed to the popular beliefs, in fact, &lt;em&gt;does not&lt;/em&gt; normally implement the SFTP protocol.&lt;/p&gt;

&lt;p&gt;It is indeed the case in &lt;em&gt;some&lt;/em&gt; operating systems, but the canonical version of &lt;code class=&quot;highlighter-rouge&quot;&gt;scp&lt;/code&gt; implements the &lt;a href=&quot;http://blogs.oracle.com/janp/entry/how_the_scp_protocol_works&quot; title=&quot;How the SCP protocol works&quot;&gt;BSD RCP protocol&lt;/a&gt; which is tunneled through the Secure Shell (SSH) protocol to provide encryption and authentication. So bear this in mind and use &lt;code class=&quot;highlighter-rouge&quot;&gt;sftp&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;Another point that is worth being discussed is why one needs a separate root-owned directory tree for a chroot, instead of chrooting directly into users’ home directories. This goes back to &lt;a href=&quot;http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-2904&quot; title=&quot;MITRE CVE-2009-2904 entry&quot;&gt;CVE-2009-2904&lt;/a&gt;, when it was discovered that badass users could be able to escalate their privileges via hard links to &lt;code class=&quot;highlighter-rouge&quot;&gt;setuid&lt;/code&gt; programs that use configuration files within the chroot directory. In the end it was decided that chrooting in user-owned directories actually defeats the purpose of the exercise and additional checks were introduced to restrict the possible sets of permission of the potential chroots.&lt;/p&gt;

&lt;p&gt;Enjoy and if I have missed something in my setup please do let me know!&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <id>https://yury.zaytsev.net/press/2011/02/10/transliteration-matters</id>
        <title>Transliteration matters!</title>
        <author>
            <name>Yury V. Zaytsev</name>
            <uri>https://yury.zaytsev.net/</uri>
        </author>
        <link href="https://yury.zaytsev.net/press/2011/02/10/transliteration-matters.html" type="text/html" />
        <updated>2011-02-10T00:00:00+00:00</updated>
        <content type="html">&lt;h2 id=&quot;prelude&quot;&gt;Prelude&lt;/h2&gt;

&lt;p&gt;In Russia, just as it is the case in many other states, the passport of Russian citizen is the main document that proves the identity of the holder all over the country. There are two types of passports, however. The “internal” passport is unconditionally delivered to every citizen that is more than 14 years old. The “external” or “international” passport which serves to identify the citizens of Russian Federation abroad is not, however, delivered automatically. One should additionally apply for it and as long the authorities are satisfied with the outcome of the internal checkups performed the international passport is delivered.&lt;/p&gt;

&lt;p&gt;One small but important detail, however, is that the name of the passport holder in the internal passport is transcribed in Cyrillic script, which is a part of the writing system for the Russian language, the only national language officially recognized within the borders of Russia. Nevertheless, international treaties dictate that the name of the international passport holder should be transcribed in Latin script, which is most common among the European languages.&lt;/p&gt;

&lt;h2 id=&quot;so-is-there-a-way-out&quot;&gt;So, is there a way out?&lt;/h2&gt;

&lt;p&gt;Well, Russia is not the only country where a script different from Latin is employed. For instance, Chinese writing system is even more drastically different from Latin. However, in China the official set of transliteration rules exists called “pinyin” which allows one to transcribe Chinese words using Latin script as they are pronounced.&lt;/p&gt;

&lt;p&gt;Every sound in Chinese language has an equivalent symbol in pinyin and therefore, for each word there is only one possible transformation from traditional or simplified Chinese into Latin. It is worth noting, however, that the inverse transformation is not unique for various reasons, but this detail is not important for the sake of the argument.&lt;/p&gt;

&lt;p&gt;Obviously, a very same trick can be applied to the Cyrillic script. A lookup table can be created where each sound in the Russian language  transcribed by a set of Cyrillic letters can be identified with an unique sequence of Latin letters. Even more so, such a table has already been created and adopted during the Soviet times as the “GOST transliteration algorithm” (GOST is the national Russian standards body, which basically carries countrywide the same functions as ISO, the International Standards Organization).&lt;/p&gt;

&lt;h2 id=&quot;the-theory-meets-practice&quot;&gt;The theory meets practice&lt;/h2&gt;

&lt;p&gt;Surprisingly, however, Russian government could not care less about actually implementing a standard that it had created (or, rather, inherited from Soviets; could it be that they consider GOST transliteration rules to be tainted by communist propaganda or something along these lines?!).&lt;/p&gt;

&lt;p&gt;Back in 2000, roughly ten years after the destruction of the USSR, when I had to obtain my first international passport, they were delivered by the Ministry of Internal Affairs (MID) and the transliteration was performed archaically.&lt;/p&gt;

&lt;p&gt;That is, one could verbally express the preferences with regards to transliteration to the clerk and negotiate a compromise. If the citizen did not express any specific requests with regards to transliteration, it was to be performed by the clerk according to a vague set of rules dubbed “French” transliteration.&lt;/p&gt;

&lt;p&gt;Later on, towards 2005, the responsibility to deliver international passports was passed on to a newly organized Federal Migration Service of the Main Office of Internal Affairs (UFMS GUVD) and the process was “streamlined”. From then on, the transliterated names were generated by the machine, however, the rules employed neither had anything to do with GOST, nor matched previously used “French” transliteration patterns.&lt;/p&gt;

&lt;p&gt;The result, however, was claimed to be objective for which reason the citizens were denied to request any alterations. In a sense, I was lucky, because at least my last name did not change, but a very annoying extra “i” appeared in my first name (“Yuriy” instead of “Yury”).&lt;/p&gt;

&lt;p&gt;Unfortunately, in the countries where the Latin script is in use people can not imagine that the government might change their names every once in a while, so in many cases I was refused on the grounds that the name of the recipient does not match the one in the passport. Basically, there was nothing that I could do and I just had to redo all the documents bearing my “old” name.&lt;/p&gt;

&lt;h2 id=&quot;where-sun-does-not-shine&quot;&gt;Where sun does not shine&lt;/h2&gt;

&lt;p&gt;Now, international passports are only valid for 5 years from the date of issue. A new law has been recently adopted which introduces so called “biometric” international passports valid for 10 years, but as usual, the implementation is lagging far behind and not only is it problematic to obtain one inside Russia, but also some consulates plainly deny such requests.&lt;/p&gt;

&lt;p&gt;In Germany, apparently, the consulate in Berlin does handle such inquiries, but as a Russian citizen, one is not allowed to come to &lt;em&gt;any&lt;/em&gt; Russian consulate in the foreign country of residence. One is only permitted to address to a specific consulate which is responsible for the particular area of residence, i.e. for Baden-Württenberg this would be the one in Frankfurt am Main. Of course, coincidentally, they make it very clear on their web page that they would not deliver any biometric passports yet (as of February 2011).&lt;/p&gt;

&lt;p&gt;So, what the hell, let us go for a “normal” one and after just 3 month of waiting time it is ready to be picked up (of course, only in person)! After spending around one hour outside in the queue among angry retired immigrants I finally made it inside.&lt;/p&gt;

&lt;p&gt;Good news is that nowadays, under the pressure from population a new service has been introduced: for a modest fee of 7.5 € you can get a stamp in your passport with your name transcribed according to the desired transliteration scheme.&lt;/p&gt;

&lt;p&gt;Oh, wait, bummer! You can not see the passport before you request the stamp. Still, I was assuming that I need “French” transliteration, because it seemed obvious to me that they were to reissue a passport with the extra “i” I needed to get rid of. However, under the tireless lead of President Medvedev’s, apparently, the software doing the transliteration was “modernized” yet again and now, somehow, it generates names transliterated à la Française! So basically I paid for nothing…&lt;/p&gt;

&lt;p&gt;Luckily, after some bargain the clerk agreed to cancel the stamp and make another one with my name transcribed as in the old passport, so finally I have both names on file and hopefully do not have to redo all the documents again. After all, they are all human, maybe just spoiled a little bit by the housing problem.&lt;/p&gt;

&lt;p&gt;As a conclusion, I admit that obviously the government knows better how I would prefer to be called, but in my humble opinion just a tiny bit of consistency would definitively not hurt!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <id>https://yury.zaytsev.net/press/2010/12/04/tcp-udp-dns-tunneling</id>
        <title>Tunneling TCP over UDP (DNS in particular)</title>
        <author>
            <name>Yury V. Zaytsev</name>
            <uri>https://yury.zaytsev.net/</uri>
        </author>
        <link href="https://yury.zaytsev.net/press/2010/12/04/tcp-udp-dns-tunneling.html" type="text/html" />
        <updated>2010-12-04T00:00:00+00:00</updated>
        <content type="html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;This short post is just meant to be a recap on what I learned during my own very personal TCP over UDP tunneling quest.&lt;/p&gt;

&lt;p&gt;First off, be mindful of the limitations of this technique. I have seen folks thinking that they are going to bypass TCP traffic shaping by tunneling it over UDP, since sometimes ISPs don’t implement explicit policing for UDP, at least for known protocols, such as DNS, because, frankly speaking, from the ISP’s POV it doesn’t really make much sense. More precisely, the flood of UDP packets will still reach their network, no matter whether they decide to queue and drop them to make you suffer or not.&lt;/p&gt;

&lt;p&gt;This simply doesn’t work! UDP is mostly designed for streaming-like usage, i.e. you are not getting acknowledgements on received packets and server just goes on sending. Of course bi-directional communication is still possible in this scenario, but think of how much the performance of the applications that are designed with TCP in mind is going to degrade! It’s just not worth it. Don’t hurt your data! And if you are still thinking about re-implementing a better TCP on top of UDP (there must be no other reason why people keep polishing their TCP stacks for decades, other than that they are more stupid than you are), remember about the great demise of µTorrent &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;g&amp;gt;&lt;/code&gt; and think again.&lt;/p&gt;

&lt;p&gt;Having that said, there might be valid reasons (of course, this depends on whether you include marginally unlawful activity in your definition of “valid” or not) to tunnel TCP over UDP. Such as, for instance, bypassing overly restrictive firewalls when you are set out to leak sensitive information to the outside world (an obligatory nonsensical example, since this goal can be achieved in hundreds of easier and safer ways).&lt;/p&gt;

&lt;h2 id=&quot;tunneling-tcp-streams-over-dns&quot;&gt;Tunneling TCP streams over DNS&lt;/h2&gt;

&lt;p&gt;Now it is important to realise, that the fact that you are tunneling your traffic over UDP itself is of no help. You need to tunnel over something, that is not explicitly meant to be a bi-directional communication channel and that does not involve direct communication with the terminator of your tunnel.&lt;/p&gt;

&lt;p&gt;For instance, there’ve been strange ideas to establish TCP over ICMP tunnels, but those are much more suitable to use as covert channels, since no sane sysop will leave such a blatant hole in his network. This is where DNS comes in. The great thing about DNS is that it is recursive by nature, which means that one can force a compliant DNS server to ask a very specific one (authoritative for the domain in question) to resolve a hostname if it doesn’t know how to do it. Also, it’s very commonly used and mostly considered harmless, which is also to our advantage.&lt;/p&gt;

&lt;p&gt;That’s why there are so many tools for this particular purpose and they mostly work even now that many sysops are starting to recognise that security is not something that one should keep taking lightly on the networks where sensitive information is transmitted.&lt;/p&gt;

&lt;h2 id=&quot;overview-of-the-available-tools&quot;&gt;Overview of the available tools&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;All this madness started with the legendary native implementation called &lt;a href=&quot;http://savannah.nongnu.org/projects/nstx/&quot; title=&quot;NSTX at Savannah&quot;&gt;NSTX&lt;/a&gt; by Tamas Szerb, which, however, doesn’t seem to be under active development anymore and even hardly works.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Later a Java re-implementation called &lt;a href=&quot;http://tadek.pietraszek.org/projects/DNScat/&quot; title=&quot;The original DNSCat&quot;&gt;DNSCat&lt;/a&gt; by Tadek Pietraszek appeared. As the name suggests it’s more like netcat in spirit. Based upon CNAME requests, which is painfully slow, but less prone to blocking.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Dan Kaminsky (yes, the same guy which once succeeded in adding some randomness to the name resolution &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;g&amp;gt;&lt;/code&gt;) came up with a hacky ssh ProxyCommand compliant Perl script called &lt;a href=&quot;http://www.doxpara.com&quot; title=&quot;OzymanDNS by Dan Kaminsky&quot;&gt;OzymanDNS&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Another native effort is called &lt;a href=&quot;http://code.kryo.se/iodine/&quot; title=&quot;The iodine project&quot;&gt;iodine&lt;/a&gt; and seems to be pretty active, lead by two Swedish guys, Bjorn Andersson and Erik Ekman.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Yet another Java re-implementation exists by Tim Valenzuela of &lt;a href=&quot;http://analogbit.com/software/tcp-over-dns&quot; title=&quot;The tcp-over-dns project&quot;&gt;tcp-over-dns&lt;/a&gt; fame. This is the one I’ve settled with. Works with TXT records by default, hopefully the author will implement CNAME support as well.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There is an actively supported native cross-platform implementation called &lt;a href=&quot;http://www.skullsecurity.org/wiki/index.php/Dnscat&quot; title=&quot;The new dnscat&quot;&gt;dnscat&lt;/a&gt; by Ron Bowes.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;miscellaneous-hints&quot;&gt;Miscellaneous hints&lt;/h2&gt;

&lt;p&gt;Here are the assorted things that I’ve learned over the past couple of days:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Absolutely make sure that your DNS set up is correct (if you try to take a shortcut and put the IP address of your end point in the NS record directly the magic won’t happen):&lt;/p&gt;

    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  tunnel.domain.tld.	IN	NS	ns.domain.tld.
  ns.domain.tld.	IN	A	123.123.123.123
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you want to map an arbitrary port (think ssh) through dnscat, do it this way:&lt;/p&gt;

    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  mknod backpipe p
  nc 127.0.0.1 22 &amp;lt;backpipe | java -cp ... net.ibao.dnscat.DNScatServer -o tunnel.domain.tld -p 9876 1&amp;gt;backpipe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The bash &lt;code class=&quot;highlighter-rouge&quot;&gt;while&lt;/code&gt; syntax to make a resilient service is as follows:&lt;/p&gt;

    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; :
  &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      /path/to/server
  &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you are running Ubuntu + ufw just put your REDIRECT rule in &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/rc.local&lt;/code&gt;, the rest goes to &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/ufw/before.rules&lt;/code&gt;. Don’t forget to enable forwarding in &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/ufw/sysctl.conf&lt;/code&gt; (reboot to apply).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The correct dig syntax is as follows (just FYI, I always keep forgetting it):&lt;/p&gt;

    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  dig any sub.domain.tld @ns.server.tld
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I always forget the correct nmap syntax for host fingerprinting and keep on googling:&lt;/p&gt;

    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  sudo nmap -A host.tld
  sudo nmap -O host.tld
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Nice ~/.ssh/config to use with tcp-over-dns (commented part is for DNSCat)… Enjoy a SOCKS5 proxy server on localhost:8888.&lt;/p&gt;

    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  Host tunnel
    HostName localhost
    Compression yes
    ForwardX11 yes
    IdentityFile ~/.ssh/id_dsa
    #Port 22
    Port 9876
    ServerAliveInterval 30
    TCPKeepAlive yes
    User name
    #ProxyCommand $HOME/bin/dnscat-0.02/DNScatClient -o tunnel.domain.tld
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null
    DynamicForward 8888
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is left to be done is probably to find a nice and easy to use socksifier for Linux, so that one, for instance, can do something along the lines of:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;socksify git fetch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and enjoy happy coding while on train.&lt;/p&gt;

&lt;p&gt;Thanks to everyone involved!&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <id>https://yury.zaytsev.net/press/2010/10/29/installing-solaris-10-sun-blade-1000</id>
        <title>Installing Oracle Solaris 10 on Sun Blade 1000</title>
        <author>
            <name>Yury V. Zaytsev</name>
            <uri>https://yury.zaytsev.net/</uri>
        </author>
        <link href="https://yury.zaytsev.net/press/2010/10/29/installing-solaris-10-sun-blade-1000.html" type="text/html" />
        <updated>2010-10-29T00:00:00+00:00</updated>
        <content type="html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;So, you are a happy owner that wants to get latest and greatest Oracle Solaris running on a legendary &lt;code class=&quot;highlighter-rouge&quot;&gt;Sun Blade 1000&lt;/code&gt; workstation with glorious double UltraSPARC III CPUs and a fair 1 Gb of RAM? Follow on!&lt;/p&gt;

&lt;h2 id=&quot;hardware-requirements&quot;&gt;Hardware requirements&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Check the version of OpenBoot firmware that your blade is equipped with. There is a known issue with OpenBoot 4.2 which prevents the workstations, having Toshiba DVD-ROM installed from booting from DVD media.&lt;/p&gt;

    &lt;p&gt;This is a highly annoying problem. In general, two kinds of advices can be found on the Internets:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;Find another DVD drive, replace the built-in Toshiba drive with a new one and hope that it will work. I have not tested this suggestion, but it might work for you.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Find the latest firmware upgrade, re-flash the firmware and re-install the OS. This solution will be described later on this page.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Be mindful of the fact, that graphical system requires at least 768 Mbs of RAM to be available. If this is not the case, you will only be able to use the text console. In my case, I had to open up the Blade and add more RAM from a donor machine that was missing a sound card.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;re-flashing-the-firmware&quot;&gt;Re-flashing the firmware&lt;/h2&gt;

&lt;p&gt;Initially, I did not have an IDE DVD drive at hand, so I decided to go for the firmware upgrade, which proved to be more challenging that I would have ever expected. First, it took awhile to find out what is the internal Patch Number assigned to this particular firmware upgrade. For the record, it is &lt;code class=&quot;highlighter-rouge&quot;&gt;111292-17&lt;/code&gt;. Second, it turned out, that apparently you need an active support contract with Oracle to be eligible for this download. This hindrance can be effectively worked around by Googling for &lt;code class=&quot;highlighter-rouge&quot;&gt;111292-17.zip&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now that the longed-for update is there, it is time to ask oneself how to proceed with the upgrade, given that the previously installed system is completely hosed (in this particular case, I have found some completely inoperable remnants of Solaris 8 scattered around the drive). The solution is easy: find a working Solaris LiveCD for SPARC, set up the networking, download the update from a private web server and proceed with the upgrade.&lt;/p&gt;

&lt;p&gt;Investigation quickly revealed that &lt;a href=&quot;http://www.milax.org&quot; title=&quot;MilaX, an OpenSolaris-based LiveCD&quot;&gt;MilaX&lt;/a&gt; is a perfect candidate for the job. Download the latest SPARC ISO (or Google for &lt;code class=&quot;highlighter-rouge&quot;&gt;milax032sparc.iso&lt;/code&gt; if the website has already been taken down) and burn it on a &lt;em&gt;CD&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now, OpenBoot. One of the beauties of OpenBoot is that you can invoke the BIOS at any time on a running system (not that this might be the safest thing to do, though). So, in order to boot from the freshly burned image, press Stop+A on the Sun keyboard and type the following at the prompt:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ok? setenv auto-boot? false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Reboot the machine and after inserting the CD and type the following to boot from the optical drive:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ok? boot cdrom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The CD will spin up and after some time you will be presented with the login screen. Log into the system as user &lt;code class=&quot;highlighter-rouge&quot;&gt;alex&lt;/code&gt; with password &lt;code class=&quot;highlighter-rouge&quot;&gt;alex&lt;/code&gt;. Become root through &lt;code class=&quot;highlighter-rouge&quot;&gt;su -&lt;/code&gt; with password &lt;code class=&quot;highlighter-rouge&quot;&gt;root&lt;/code&gt;. Time to set the networking up and fetch the update:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; ifconfig eri0 down
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; ifconfig eri0 192.168.0.1 netmask 255.255.255.0 up
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; route add default 192.168.0.254
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /etc/resolv.conf
&lt;span class=&quot;go&quot;&gt;    nameserver 192.168.0.254
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;    ...
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;    Ctrl+D
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; wget http://server.lan/flash-update-Blade1000-latest
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; wget http://server.lan/flash-update-Blade1000-old
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; wget http://server.lan/unix.flash-update.SunBlade1000.sh
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; chmod +x unix.flash-update.SunBlade1000.sh
&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt; ./unix.flash-update.SunBlade1000.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Answer &lt;code class=&quot;highlighter-rouge&quot;&gt;yes&lt;/code&gt; and keep the fingers crossed; the magic will happen and the machine will reboot itself when the update is completed.&lt;/p&gt;

&lt;h2 id=&quot;installing-solaris-10-proper&quot;&gt;Installing Solaris 10 proper&lt;/h2&gt;

&lt;p&gt;To be described. Refer to Blastwave. Provide some references, e.g. to Cuddletech.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Overall, the firmware upgrade process went smoothly and is not nearly as scary as it sounds. However, few issues, such as the difficulty to find the patch and inability to use previously installed system to perform the upgrade made it necessary to do some prior research.&lt;/p&gt;

&lt;p&gt;Solaris 10 installation went extremely smoothly and left feelings of mixed joy and sorrow. Even though I did the mistake of not pre-allocating space for the ZFS database and online upgrades, I probably will not need them anytime soon, so overall it seemed to be too easy to not have a catch.&lt;/p&gt;

</content>
    </entry>
    

</feed>
